微信小程序架构分析 (中)

2017-01-12 09:53:48来源:oschina作者:乐搏学院人点击

本文探讨一下小程序的 view 模块和 service 模块是如何构成的。 你可以在app.nw/app/dist/weapp/tpl/pageFrameTpl.js 和app.nw/app/dist/weapp/tpl/appserviceTpl.js 文件内找到页面的模板。


打开微信web 开发者工具,然后输入 openVendor() 便会打开 WeappVendor这个目录,这里包含了 view 模块和 service 模块使用的几个核心文件:

wcc 可执行程序,用于将 wxml 转为 view 模块使用的 js 代码,使用方式为wcc xxx.wxml


wcsc 可执行程序,用于将 wxss 转为 view 模块使用的 css 代码,使用方式为 wcsc xxx.wxss


WAService.js 提供 service 模块大部分功能,下面会有详细介绍


WAWebview.js 提供 view 模块大部分功能,下面会有详细介绍

view 页面详解

view 页面的 template 如下:




















其中 会在 dev 模式开启后被替换为一个时间锚点,例如:


会被 WAWebview.js 内代码替换


之间暂时没有被使用到


会被 wcc 命令生成后的 js 代码替换


除了上面这些,页面上还会被插入页面和应用的 style 标签,如:


这里的 wxss 文件包含的是原始 wxss 文件转换后的 css


以及生成 DOM 的启动脚本:


WAWebview.js 文件中的各个模块(行号为 jsbeautify 之后代码行号,开发者工具版本:092300):

1-77 行: WeixinJSBridge 对象兼容层,这个大概只会在调试时用到,因为开发时和运行时页面都会被后台以注入的方式添加 WeixinJSBridge 这个对象。我们可以通过这段代码看到它暴露的方法: invoke invokeCallbackHandleron publish subscribe subscribe subscribeHandler。


78-235 行:Reporter 对象,它的作用就是发送错误和性能统计数据给后台


236-596 行:wx 对象,页面的核心之一,一方面封装 WeixinJSBridge 的 invokeMethod 方位为易于调用的形式(例如 redirectTo, navigateTo等),另一方面封装 WeixinJSBridge 回调方法,调用者可以使用wx.onAppDataChange(callback) 添加数据变更的回调函数,最后提供wx.publishPageEvent 发送页面事件到后台


607-1267 行:wxparser 对象,提供 dom 到 wx element 对象之间的映射操作,提供元素操作管理和事件管理功能


1268-1285 行:转发 window 上的 animation 和 transition 相关的动画事件到 exparser


1286-1313 行:订阅并转发 WeixinJSBridge 提供的全局事件到 exparser


1324-1345 行:转发 window 上的 error 以及各种表单事件到 exparser


1347-3744 行:使用 exparser.registerBehavior 和exparser.registerElement 方法注册各种以 wx- 做为标签开头的元素到 exparser


3744-4498 行:virtual dom 渲染算法实现,提供 diff apply render 等方法,该模块接口基本与virtual-dom一致,这里特别的地方在于它所 diff 和生成的并不是原生 DOM,而是各种模拟了 DOM 接口的 wx element 对象


4599-4510 行:插入默认样式到页面

从页面 data 到 dom 的主要流程如下:

varvtreevarrootNodedocument.addEventListener("generateFuncReady",function(e){
vargenerateFunc=e.detail.generateFunc;
wx.onAppDataChange(function(obj){
//合并data到现有data
DataStore.setData(obj.data)
//生成virtualdom的javascriptplainobject
varprops=generateFunc(DataStore.getData())
//第一次渲染
if(obj.options.firstRender){
vtree=createVirtualTree(props,true)
rootNode=vtree.render()
rootNode.replaceDocumentElement(document.body)
wx.initReady()
}else{
varother_vtree=createVirtualTree(props,false)
varpatches=vtree.diff(other_vtree)
patches.apply(rootNode)
vtree=other_vtree
document.dispatchEvent(newCustomEvent("pageReRender",{}));
}
})})

上面的 DataStore 对象提供合并和获取当前页面 data 对象的功能,其实现如下:

varDataStore=(function(){
vardata={}
return{
getData:function(){
returndata
},
setData:function(e){
for(vartine){
for(varn=(0,parsePath)(t),o=data,a=void0,s=void0,c=0;ca&&(a[s]=e[t])
}
}
}})()//解析key为data内对象的路径字符串functionparsePath(e){
for(vart=e.length,n=[],i="",r=0,o=!1,a=!1,s=0;svarc=e[s];
if("//"===c)s+1elseif("."===c)i&&(n.push(i),i="");
elseif("["===c){
if(i&&(n.push(i),i=""),0===n.length)thrownewError("pathcannotstartwith[]:"+e);
a=!0,o=!1
}elseif("]"===c){
if(!o)thrownewError("musthavenumberin[]:"+e);
a=!1,n.push(r),r=0
}elseif(a){
if(c<"0"||c>"9")thrownewError("onlynumber0-9couldinside[]:"+e);
o=!0,r=10*r+c.charCodeAt(0)-48
}elsei+=c
}
if(i&&n.push(i),0===n.length)thrownewError("pathcannotbeempty");
returnn}

可以看到,每次 data 变化之后,小程序就会开始整个页面的 diff patch 过程。


对于原生实现的组件, exparser 会在监视到数据变化后发送对应事件到 WeixinJSBridge。


service 页面详解

service 页面会被被拼接为以下的样子:












除了配置和开发者编写的页面、app.js,页面还在加载了 asdebug.js 和 WAService.js 两个文件。


asdebug.js 文件位于 nwjs 项目目录下,路径为app/dist/weapp/appservice/asdebug.js。 它包含了两个部分,一个是 WeixinJSBridge 针对 service 模块的实现,另一块是一些方便命令使用的接口, 例如:help() 会告诉你一些可用的函数:



该文件只会在开发者工具内被引入,如果小程序在微信内运行,应该会由微信底层提供 WeixinJSBridge。


WAService 负责 service 模块的一些核心逻辑,它包含以下部分 (行号为 jsbeautify 之后代码行号,开发者工具版本:092300):

1-78 行: 跟 WAWebview.js 一样的 WeixinJSBridge 兼容模块


79-245 行: 跟 WAWebview.js 一样的 Reporter 模块


246-1664 行:比 WAWebview.js 中 wx 功能更为丰富 wx 接口模块


1665-2304 行:appServiceEngine 模块,提供 Page,App,GetApp 接口


2305-2360 行: 为 window 对象添加 AMD 接口 require define

现在的 WAService 还有有很多地方依赖 window 对象,所以很有可能它在微信中和开发者工具内一样,依然运行于 webview 标签之内。


下篇介绍如何自己动手建立一个可以运行小程序的环境,欢迎关注。

登录乐搏学院官网http://www.learnbo.com/


或关注我们的官方微博微信,还有更多惊喜哦~



作者:赵启明 链接:https://zhuanlan.zhihu.com/p/22765476

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台