最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Weex中js服务的理解

    正文概述 掘金(一拳小和尚)   2021-02-18   677

    js服务

    weex中注册js服务,会在当前运行的js环境中注入一个对应service的create方法返回的对象,这个对象有两种返回形式:

    1. 在返回对象的instance上声明一个实例服务;
    2. 直接在返回对象对象上声明一个服务。

    如下面代码中的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服务官方文档


    起源地下载网 » Weex中js服务的理解

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元