彻底理解weex原理

思路

我们要从weex的runtime-jsFramework源码出发理解weex的实现原理。

runtime-jsFramework

image.png

entries

各种前端框架的入口文件,比如vue.js:

import setup from './setup'
import * as Vue from 'weex-vue-framework'

setup({ Vue })

以index.js为入口会编译所有框架的版本。

import * as Vanilla from './vanilla/index'
import * as Vue from 'weex-vue-framework'
import * as Weex from './legacy/index'
import Rax from 'weex-rax-framework'

export default {
  Vanilla,
  Vue,
  Rax,
  Weex
}

api

做的事情包括,初始化第三方框架,传入weex提供的config参数中的一些对象;返回全局api供第三方前端框架和native调用。

const config = {
  Document, Element, Comment, Listener,
  TaskCenter,
  sendTasks (...args) {//调用原生代码
    if (typeof callNative === 'function') {
      return callNative(...args)
    }
    return (global.callNative || (() => {}))(...args)
  }
}

Document.handler = config.sendTasks

第三方前端框架可以根据config中参数进行初始化。
暴露的全局api供第三方前端框架调用

  createInstance,//创建实例
  createInstanceContext,//创建实力上下文对象
  getRoot,//获得根实例
  getJSFMVersion,//获得jsm版本
  getDocument: getDoc,//获得当前的document全局对象
  registerService: register,//注册服务
  unregisterService: unregister,//取消注册
  callJS (id, tasks) {//callJS,native通过这个方法统一调用js方法
    const framework = frameworks[getFrameworkType(id)]
    if (framework && typeof framework.receiveTasks === 'function') {
      return framework.receiveTasks(id, tasks)
    }
    return receiveTasks(id, tasks)
  }
  adaptMethod('registerComponents', registerComponents)//注册组件
  adaptMethod('registerModules', registerModules)//注册模块
  adaptMethod('registerMethods');
  ['destroyInstance', 'refreshInstance'].forEach(genInstance)//注册生命周期函数

在init函数中我们发现还调用了initHandler函数,这个函数初始化任务处理中心的方法,是brige/TaskCenter.js中的init函数,这个函数为TaskCenter类的原型上挂载了诸多对外的方法,这些方法最终是调用的原生方法处理。

const DOM_METHODS = {
    createFinish: global.callCreateFinish,
    updateFinish: global.callUpdateFinish,
    refreshFinish: global.callRefreshFinish,

    createBody: global.callCreateBody,

    addElement: global.callAddElement,
    removeElement: global.callRemoveElement,
    moveElement: global.callMoveElement,
    updateAttrs: global.callUpdateAttrs,
    updateStyle: global.callUpdateStyle,

    addEvent: global.callAddEvent,
    removeEvent: global.callRemoveEvent,
    __updateComponentData: global.__updateComponentData
  }

WeexInstance
是暴露给开发者使用的weex的对外界接口,我们可以从其构造函数概览可以全局访问的接口:

constructor (id, config, data) {
    setId(this, String(id))
    this.config = config || {}//全局配置,包括环境变量,设备信息等
    this._nativeData = data || {}//原生初始化传递过来的数据
    this.document = new Document(id, this.config.bundleUrl)//模拟dom的document对象
    this.requireModule = this.requireModule.bind(this)//引入模块
    this.importScript = this.importScript.bind(this)//引入js代码,立即执行
    this.isRegisteredModule = isRegisteredModule //检测模块是否存在
    this.isRegisteredComponent = isRegisteredComponent //检测组件是否存在
  }

这些是我们开发weex界面可以直接调用的。

brige

是js与native的连接器,用于js调用native代码,处理管理事件回调函数
CallbackManager.js:回调函数管理器,包括组件hook函数
Handler:任务处理器,用于调用原生方法

//可调用的原生方法
const handlerMap = {
  createBody: 'callCreateBody',
  addElement: 'callAddElement',
  removeElement: 'callRemoveElement',
  moveElement: 'callMoveElement',
  updateAttrs: 'callUpdateAttrs',
  updateStyle: 'callUpdateStyle',
  addEvent: 'callAddEvent',
  removeEvent: 'callRemoveEvent'
}

Listener:Handler对外的访问接口(封装),为调用native的方法或者说发送调用信号提供可分批的操作。
Receiver.js:接收原生发送的事件和组件回调

export function receiveTasks (id, tasks) {
  const document = getDoc(id)
  if (!document) {
    return new Error(`[JS Framework] Failed to receiveTasks, `
      + `instance (${id}) is not available.`)
  }
  if (Array.isArray(tasks)) {
    return tasks.map(task => {
      switch (task.method) {
        case 'callback': return callback(document, ...task.args)
        case 'fireEventSync':
        case 'fireEvent': return fireEvent(document, ...task.args)
        case 'componentHook': return componentHook(document, ...task.args)
      }
    })
  }
}

TaskCenter:
是任务处理中心,处理以下事务:

  • 通过CallbackManager管理回调函数
  • 通过CallbackManager管理hook回调
  • 处理dom操作(通过向原生发送指令)
  • 处理component组件方法调用
  • 处理module模块方法调用

其中回调相关即回调函数和hook回调都是通过callbackManager管理,dom操作通过全局config对象上的sendTasks调用global.callNative向原生发送指令,component和module通过各自的handler处理,分别为定义到global上的callNativeComponent和callNativeModule方法,不存在的话就同样调用sendTasks方法。

vdom

index.js:入口文件

Commen.js:注释结点

Document:对应浏览器document的vdom实现

Element:元素结点的vdom实现

Node.js:vdom的基础实现,基类

WeexElement.js:注册weex组件的文件,有一个map集合保存所有注册了的组件,并为组件添加组件对应的方法。

operation.js:所有的dom操作方法定义在此文件中

思维导图

根据我们上面的整理和理解,接下来把知识点通过思维导图的形式进行梳理,使得知识点关联起来,脉络更清晰,方便我们理解和记忆。

上面就是我们对runtime-jsFramework的梳理和理解了,接下来我们通过阅读weex-vue-framework的原理进一步理解这部分代码的使用。

weex-vue-framework

首先我们发现weex-vue-framework主要做了如下几件事:

  1. createInstanceContext

    创建实例,处理weex实例

  2. createVueModuleInstance

    创建Vue实例,并做对weex的适配

  3. 挂载weex提供的api到Vue实例上,如document,taskCenter等

通过上面的理解我们发现,weex运行时js框架实际上就是为前端框架提供了一系列api,包括dom操作、事件处理等。

weex框架分层理解

  • Vue.js、Rax.js:前端框架

  • weex-js-frameworlk:调用C++native接口,通过JSBrige调用Android和IOS,封装了一系列的dom操作,taskCenter管理回调、模块和组件方法。

  • weexsdk(c++):weex的c++引擎,用于连接Android/ios,封装了统一的dom体系,回调事件管理,模块、组件管理和调用。

  • Android/ios:原生UI、组件,功能模块等。

总结

通过上面的学习和理解,我们可以这样理解weex的实现原理:

  • 首先我们通过weexsdk(c++)把Android和IOS的UI封装成统一的vdom和事件体系;
  • runtime-jsFramework则是对这个vdom和事件体系的进一步封装和实现,它可以直接调用native代码与Android和IOS等平台交互;
  • 最后是诸如Vue.js和Rax.js的前端框架,它们可以使用runtime-jsFramework封装的vdom和事件体系,就像我们在浏览器端一样使用。

以上就是自己在阅读了weex的runtime-jsFramework和weex-vue-framework的源码后对weex实现原理的总结,如果对您有帮助,还望不吝点赞,如有错误,还望指正,多谢~~~

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一拳小和尚LXY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值