Weex架构原理
- JSFRAM 负责和JS框架(
VUE/RAX)交互,生成DomTree,将数据传给WeexCore - WeexCore 有3部分
- JSSide: 运行在JS进程中,负责jsbinding、创建、管理js的vm、context
- CoreSide: 运行在主进程中,负责layout以及将
RenderTree以命令形式交给Platform绘制 - IPC: 跨进程通信
- Platform(Android/iOS)
- 将
RenderTree转化为平台对应的ViewTree,进行渲染 - native能力调用提供
- 将
- JSRuntime: 底层封装
JSC/V8接口,WeexCore使用JSRuntime和jsengine通信
Weex架构图如下
流程
从一个例子说起
render(){
<div>
<div>
<text>hello</text>
</div>
<div>
<img src="xxx"></img>
</div>
</div>
}渲染流程
JS世界
上述的的demo代码,
- 会触发框架
Rax的dom构建操作, - 构建dom会调用到W3C标准的
DomApi DomApi实际上是挂载到了weex的jsfm上jsfm持有一颗dom树
div
div div
text imgJSFM 在更新dom树时,会将更新指令序列化成json,同步给weexcore,比如上述结构,会生成类似下面指令,
//add div
{"action":"addElement","type":"div","id":1}
//将text add 到上面的div上
{"action":"addElement","type":"text","id":2 ,"parent":1, "attr":{"value":"hello"}}
//。。。然后通过事先binding好的js函数callAddElement(...),传给weexcore
WeexCore-JSSide
WeexCore的js端,在启动时,就通过JSRuntime向JSEnginebinding了若干native函数,比如addElement
//weex_global_binding.cpp
CLASS_METHOD_CALLBACK(WeexGlobalBinding, callAddElement)在收到这个命令后,会直接通过IPC将命令转给主进程的接收者。
注意,weex当前模式是双进程方案
- JSEngine、js代码、WeexCore-JSSide运行在JS进程中
- LayoutEninge、WeexCore-CoreSide、Platform相关运行在主进程中
IPC通信
。。。
WeexCore-CoreSide
主进程注册了IPC的listener
static std::unique_ptr<IPCResult> HandleCallAddElement(IPCArguments *arguments){
//..
WeexCoreManager::Instance()->script_bridge()->core_side()->AddElement(...)
);
void CoreSideInScript::AddElement(...) {
RenderManager::GetInstance()->AddRenderObject(...);
}最终会将渲染命令交给RenderManager
bool RenderManager::AddRenderObject(...) {
RenderPageBase *page = GetPage(page_id);
if (page->is_platform_page()) {
RenderObject *child = Wson2RenderObject(data, page_id,
page->AddRenderObject(parent_ref, index, child);
}
bool RenderPage::AddRenderObject(const std::string &parent_ref,
int insert_posiotn, RenderObject *child) {
//添加到rendertree上,并且触发layoutengine进行laoyout
parent->AddRenderObject(insert_posiotn, child);
//向platform端,发送渲染指令
SendAddElementAction(child, parent, insert_posiotn, false);
return true;
}RenderManager中将节点添加到RenderTree中,然后向platform端发送渲染指令
Platform
以Android为例,上层收到指令后,
- 首先将根据节点信息,生成
WXComponent, - 然后根据
Component上的信息,生成对应的view(img、text) - 将view add到
viewtree上 - 下一帧显示
//GraphicActionAddElement.java
public void executeAction() {
super.executeAction();
//添加到component树上
parent.addChild(child, mIndex);
//根据component创建对应的view,并且添加到viewtree上
parent.createChildViewAt(mIndex);
child.applyLayoutAndEvent(child);
child.bindData(child);
}你看,逻辑其实很简单,一点都不复杂。
Api能力调用
和渲染流程类似
JSApi->JSFM->WeexCoreJSSide->IPC->WeexCoreCoreSide->Platform->Module这里就不细讲了。
Weex/RN这类方案的优/缺点
优点
- 将前端世界和Native世界无缝结合了起来,前端同学可以使用JS快速迭代业务
- 借助JS天生的动态能力,动态发版赋予电商类需要快速迭代业务发版难、发版慢的问题
- 性能远远强于H5,比较接近native的体验。
缺点
- 三端不一致问题(JS、iOS、Android),三个世界各有个的开发理念,强行融合必然会产生冲突。这是这类方案在基因上就有的问题,无法彻底解决。
- 维护成本问题,链路太长,技术栈太多。一旦除了问题,就需要前端同学、native同学(Android、iOS)一起攻关,费时费力。
…