js服务
weex中注册js服务,会在当前运行的js环境中注入一个对应service的create方法返回的对象,这个对象有两种返回形式:
- 在返回对象的instance上声明一个实例服务;
- 直接在返回对象对象上声明一个服务。
如下面代码中的InstanceService和NormalService
service.register(SERVICE_NAME /* same string with native */, {
/**
* JSService lifecycle. JSService `create` will before then each instance lifecycle `create`. The return param `instance` is Weex protected param. This object will return to instance global. Other params will in the `services` at instance.
*
* @param {String} id instance id
* @param {Object} env device environment
* @return {Object}
*/
create: function(id, env, config) {
return {
instance: {
InstanceService: function(weex) {
var modal = weex.requireModule('modal')
return {
toast: function(title) {
modal.toast({ message: title })
}
}
}
},
NormalService: function(weex) {
var modal = weex.requireModule('modal')
return {
toast: function(title) {
modal.toast({ message: title })
}
}
}
}
},
/**
* JSService lifecycle. JSService `refresh` will before then each instance lifecycle `refresh`. If you want to reset variable or something on instance refresh.
*
* @param {String} id instance id
* @param {Object} env device environment
*/
refresh: function(id, env, config){
},
/**
* JSService lifecycle. JSService `destroy` will before then each instance lifecycle `destroy`. You can deleted variable here. If you doesn't detete variable define in JSService. The variable will always in the js runtime. It's would be memory leak risk.
*
* @param {String} id instance id
* @param {Object} env device environment
* @return {Object}
*/
destroy: function(id, env) {
}
})
源码理解
我们从源码的角度理解service的注册过程,我们可以在runtime的代码中找到创建服务的方法:
function createServices (id, env, config) {
// Init JavaScript services for this instance.
const serviceMap = Object.create(null)
serviceMap.service = Object.create(null)
services.forEach(({ name, options }) => {
if (process.env.NODE_ENV === 'development') {
console.debug(`[JS Runtime] create service ${name}.`)
}
const create = options.create
if (create) {
try {
const result = create(id, env, config)
Object.assign(serviceMap.service, result)
Object.assign(serviceMap, result.instance)
}
catch (e) {
console.error(`[JS Runtime] Failed to create service ${name}.`)
}
}
})
delete serviceMap.service.instance
Object.freeze(serviceMap.service)
return serviceMap
}
我们看到在第3行和第4行分别创建了一个serviceMap对象和一个serviceMap上的service对象,这是用来将来保存我们通过两种方式创建的服务的;
接下来我们看第10行,如果注册的服务有create方法,那么我们取它的返回值为result,接下来分别把result上的属性复制到serviceMap.service,把result.instance上的属性复制到serviceMap上,最后返回这个serviceMap。
那么这个serviceMap是怎么放到全局的呢,我们继续查找源码,可以跟踪到createInstanceContext方法,
function createInstanceContext (id, options = {}, data) {
const weex = new WeexInstance(id, options, data)
const bundleType = options.bundleType || 'Vue'
instanceTypeMap[id] = bundleType
const framework = runtimeConfig.frameworks[bundleType]
if (!framework) {
return new Error(`[JS Framework] Invalid bundle type "${bundleType}".`)
}
// prepare js service
const services = createServices(id, {
weex,
config: options,
created: Date.now(),
framework: bundleType,
bundleType
}, runtimeConfig)
Object.freeze(services)
// prepare runtime context
const runtimeContext = Object.create(null)
Object.assign(runtimeContext, services, {
weex,
getJSFMVersion,
requireModule: (...args) => weex.requireModule(...args),
__WEEX_CALL_JAVASCRIPT__: receiveTasks,
services // Temporary compatible with some legacy APIs in Rax
})
Object.freeze(runtimeContext)
// prepare instance context
const instanceContext = Object.assign({}, runtimeContext)
if (typeof framework.createInstanceContext === 'function') {
Object.assign(instanceContext, framework.createInstanceContext(id, runtimeContext, data))
}
Object.freeze(instanceContext)
return instanceContext
}
这个方法是weex的runtime用来创建一个实例的上下文运行环境的,我们看到代码的第12行,调用了createServices来创建services对象,而这个services就是我们上面说的serviceMap对象了。
接下来我们看到在第21行创建了一个空的对象作为运行时的上下文环境,紧接着在22行,把services等对象上的属性复制到这个上下文对象上了,而上下文环境上的属性我们可以当做全局变量来使用。
不好理解的话我们可以结合上面注册的服务的例子,想象一下createInstanceContext最后返回这样一个对象:
{
service:{
NormalService:function(weex){
//...
}
},
InstanceService:function(weex){
//...
}
weex:weex,
getJSFMVersion:getJSFMVersion,
__WEEX_CALL_JAVASCRIPT__
}
这个对象上的属性会被weex的底层注入到全局上下文运行环境中,即这个对象上的属性是全局变量。
使用
因此我们就知道service如何在weex中使用了
<script>
var _InstanceService = new InstanceService(weex)
var _NormalService = new service.NormalService(weex)
module.exports = {
created: fucntion() {
// called modal module to toast something
_InstanceService.toast('Instance JSService')
_NormalService.toast('Normal JSService')
}
}
</script>
serviceMap是在instance的create之前服务的create获取的,因此,要想使用service,需要在实例创建之前调用原生平台的代码执行js服务的注册代码完成服务的注册。
Android和IOS原生平台的注册代码这里不再赘述,参见下面的官方文档即可。
参考文档:js服务官方文档
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!