应用程序开发公司
软件开发

针对您的项目需求及预算规划量身制定方案

个体/中小企业/集团/政府机构/行业组织 了解详情 了解详情

微信小程序架构分析《一》调试技巧,模块构成,理念分析

发布时间:2024-01-01 00:00 浏览次数:48

本文分成以下几个部分:


小程序调试技巧


小程序主要模块形成


小程序模块间通信


设计理念分析


小程序调试技巧


微信开发者工具预设停止使用了右键关上调试面板功能,我们可以修正开发者工具部分代码去除该管制。


找出 app.nw 项目根目录,Mac 下为/Applications/wechatwebdevtools.app/Contents/Resources/app.nw


采用 js-beautify 对代码批量格式化:


cd /Applications/wechatwebdevtools.app/Contents/Resources/app.nw find . -type f -name '*.js' -not -path "./node_modules/*" -not -path "./modified_modules/*" -exec js-beautify -r -s 2 -p -f '{}' \;


注解掉文件 app/dist/app.js 44 行及和app/dist/components/simulator/webviewbody.js 149 行preventDefault 调用。101100 版本还须要修正 package.json 文件,换成 --disable-devtools。


继续执行回去以上操作方式就可以右键关上页面的调试面板了,须要特别注意的就是,采用 view 页面的面板后可以引致 wxml 面板不容用,touch 事件无法积极响应等种种问题,恳请谨慎采用。


通过代码可以辨认出,在布局目录下嵌入 config.json 文件,然后重新加入{isDev:true} 可以投入使用开发者工具所谓的调试模式, 但是我在布局后程序无法正常启动,只好暂时先退出这种方式。


小程序主要模块形成


小程序自身分成两个主要部分单一制运转:view 模块和 service 模块。在开发者工具中,它们单一制运转于相同的 webivew tag 中。


view 模块负责管理 UI 表明,它由开发者撰写的 wxml 和 wxss 切换后代码以及微信提供更多有关辅助模块共同组成。 一个 view 模块对应一个 webview 组件(也就是我们常规认知的一个页面), 小程序积极支持同时多个 view 存有。view 模块通过 WeixinJSBridge 对象去跟后台通信。


service 模块负责管理应用领域的后台逻辑,它由小程序的 js 代码以及微信提供更多的有关辅助模块共同组成。 一个应用领域只有一个 service 进程,它同样也就是一个页面(至少在开发者工具内如此,上线后可能将运转于 WeixinJSCore 之内),与 view 模块相同的就是,它在程序生命周期内后台运转,service 模块通过与 view 模块同时实现相同但USB格式一样的 WeixinJSBridge 对象跟后台通信。


小程序模块间通信


(开发者工具内各模块通信图)


搞过微信研发有关的开发者可以对 WeixinJSBridge 这个对象有所介绍,它就是负责管理 UI 与后台 展开可视化的一个中间层。应用领域号的 WeixinJSBridge 较之与之前的微信 webview 多出 publish 和 subscribe 两个公共方法去公布和下载事件,从而展开双向通信。


service 模块的 WeixinJSBridge 对象在文件app/dist/weapp/appservice/asdebug.js 中定义, view 层的 WeixinJSBridge 在文件 app/dist/inject/jweixindebug.js 中定义。 尽管两者都采用一样的USB以及采用 postMessage 方法与后台通信,但是其内部所搞的事情确就是全然相同的, 比如 service 模块可以轻易通过 prompt 方法去通过 prompt调起底层组件,而 view 层的 WeixinJSBridge 就可以传送消息 (参照 H5与Native可视化之JSBridge技术)。


我们来看一个典型的可视化流程:


用户页面界面引爆事件


对应 view 模块发送事件后将事件PCB成所须要格式后调用 publish 方法传送:


WeixinJSBridge.publish('PAGE_EVENT', data)


data 参数举例:


{ "data": { "eventName": "onhidetap", "data": { "target": { ... }, "currentTarget": { ... }, "type": "tap", "timeStamp": 11457, "touches": [ ... ], "detail": { ... } } }, "options": { "timestamp": 1475445858336 } }


后台(开发者工具内为 nwjs 运转环境)将数据处理后发送给 service 模块,数据形例如:


{ "to": "appservice", "msg": { "eventName": "PAGE_EVENT", "data": { "data": { "eventName": "onhidetap", "data": { "target": { ... }, "currentTarget": { ... }, "type": "tap", "timeStamp": 75329, "touches": [ ... ], "detail": { ... } } }, "options": { "timestamp": 1475445858336 } }, "webviewID": 0 }, "command": "MSG_FROM_WEBVIEW" }


service 模块的 WeixinJSBridge 内反弹函数依据响起数据找出对应 view 的 page 模块后继续执行 对应名叫 eventName 指向的函数


反弹函数调用 this.setData({hidden: true}) 发生改变 data,serivce 层排序该页面 data 后向后台传送 send_app_data 和 appdataChange 事件,具体内容数据格式如下:


{ "appData": { "page/index": { ... } }, "sdkName": "send_app_data", "to": "backgroundjs", "comefrom": "webframe", "command": "COMMAND_FROM_ASJS", "appid": "touristappid", "appname": "chat", "apphash": 70475629, "webviewID": 100000 }


{ "eventName": "appDataChange", "data": { "data": { "data": { "hidden": true } }, "options": { "timestamp": 1475528706311 } }, "sdkName": "publish", "webviewIds": [ 0 ], "to": "backgroundjs", "comefrom": "webframe", "command": "COMMAND_FROM_ASJS", "appid": "touristappid", "appname": "chat", "apphash": 70475629, "webviewID": 100000 }


后台(文件 dist/components/simulator/webviewbody.js) 发送至appDataChange 事件数据后再将数据展开直观PCB, 最后发送到至 view 层。 具体内容数据格式为:


{ "to": "webframe", "msg": { "eventName": "appDataChange", "data": { "data": { "data": { "hidden": true } }, "options": { "timestamp": 1475528706311 } }, "sdkName": "publish", "webviewIds": [ 0 ], "to": "backgroundjs", "comefrom": "webframe", "command": "COMMAND_FROM_ASJS", "appid": "touristappid", "appname": "chat", "apphash": 70475629, "webviewID": 100000, "act": "sendMsgFromAppService" }, "command": "MSG_FROM_APPSERVICE", "webviewID": 0, "id": 0.10577065353216675 }


view 层的 WeixinJSBridge 发送至后台的数据,如果 webviewID 相匹配则将 data 与现有页面 data 分拆, 然后就是 virtual dom 模块展开 diff 和 apply 操作方式发生改变 dom。


小程序模块间消息传递除了界面事件和应用领域数据还包括引爆原生方法、击掌以及生命周期等类型, 尽管处置对象和处理方式相同,大体流程跟上面就是一样的。


view 模块和 service 模块的 WeixinJSBridge 都采用了 postMessage USB (参照MDN 文档) 与后台通信,但是由于该USB无法轻易与 nwjs 后台进程通信,所以开发者工具可以将 app/dist/contentscript/contentScript.js 文件作为contentScript 转化成至 view 模块和 service 模块所在页面,contentScript.js 的代码提供更多了 message 消息至 chrome.runtime通信接口的切换。


微信开发者工具拓展了 devtools 提供更多了 AppData 面板,开发者可以修正里面数据然后轻易看见 view 界面的变化效果。这里修正数据后 nwjs 可以将消息发送给 service 层,之后出现的事就跟上面 4 5 6 步一样:service 传达消息给 nwjs,最后至 view 层。


设计理念分析


小程序这样的分层设计似乎就是急于为之的,它的中间层全然掌控了程序对于界面展开的操作方式, 同时对于传达的数据和响应时间也努力做到的监控。一方面程序的犯罪行为受了很大管制, 另一方面微信可以保证他们对于小程序内容和体验存有绝对的掌控。


我们在小程序的 js 代码里面就是无法轻易采用浏览器提供更多的 DOM 和 BOM USB的,这一方面是因为 js 代码外层采用了局部变量展开屏蔽,另一方面即便我们可以操作方式 DOM 和 BOM USB,它们对应的 也就是 service 模块页面,并不能对页面产生影响。


这样的结构也说明了小程序的动画和绘图 API 被设计成分解成一个最终对象而不是一步一步继续执行的样子, 原因就是 json 格式的数据传达和解析较之与原生 API 都就是损耗相当可观的,如果频密调用很可能将损耗 过多性能,进而影响用户体验。


认知了以上机制,再对 view 模块和 service 模块的 WeixinJSBridge 予以改建,我们便不难努力做到使 小程序走在自己的环境下,这样就可以搞些手机调试以及单页面测试等操作方式。

TAG标签:
阅读推荐