微信小程序包含下面四种文件:

jsjson 配置文件wxml 小程序专用 xml 文件wxss 小程序专用 css 文件

{{ text }} Page({ data:{ text:"这是一个页面" }, onLoad:function(options){ // 页面初始化 options为页面跳转所带来的参数 }, // ........})

微信小程序只能通过其 mvvm 的模板语法来动态改变页面,本身 js 并不支持 BOM 和 DOM 操作。

从开发工具看微信小程序架构

在 mac 端直接解压应用 发现 App.nw 文件夹,即开发工具源码。可以知道该项目由 nw.js 编写; 在 package.json 文件下找到应用入口:app/html/index.html。入口 js 为 dist/app.js 我们可以看到整个编辑器的大致逻辑。

但我们关心的是构建过程,在 weapp 文件夹下存在 build.js 文件。没有找到有用的信息,只看到了 upload 模块,包括对大小限制,上传包命名。

为此怀疑,微信小程序本身和 RN 类似。是在服务端打包成 native 语言的。但是通过 Android 边框测试发现,微信小程序根本不是 native 原生内容。

原生界面效果:

wx 核心对象,包含了 wx 对象下的 api。但是这里的 api 数量远远少于官方的 api 文档数量。

我们可以在代码里面发现,wx 下注册的 api 最终都会调用 WeixinJSBridge 方法。这个方法应该是在打包的时候端上注入的。我们也可以在 WAServeice.js 中找到该方法的定义。

exparser.registerElement 为各种内置组件,注册模板,行为,属性,监听器等内容

这里我们观察到,组件:wx-video, wx-canvas, wx-contact-button, wx-map, wx-textarea 等 behaviors 都含有 "wx-native" 属性。这是不是意味着,这类组件都是 native 原生实现的呢。我们打开边框检查,发现这类组件确实都是原生的组件。

综上,微信小程序的界面有部分组件使用原生方式实现的,native 组件层在 WebView 层之上。大部分还是用前端实现的,这样解释了微信小程序的一个bug。

因为%20scroll-view%20是前端实现,在里面使用%20native%20组件,这样就无法监听滚动了。

WeixinJSBridge

组件是需要数据来渲染的,查看文档我们知道发送请求的%20api%20为%20wx.request;通过上面分析,我们知道%20wx.request%20实际调用的是%20WeixinJSBridge。现在我们看看%20WeixinJSBridge

WeixinJSBridge 真正发送处理数据请求的是这段代码;如果当前环境是 IOS, 那么调用 WKWebview 的 window.webkit.messageHandlers.invokeHandler.postMessage。如果所处环境是 android 则调用 WeixinJSCore.invokeHandler (调用的时候,默认会带上当前 webviewID)。

WAService.js

在对 WeixinJSBridge.js 分析中,我们并没有发现前端的通讯功能,路由能力,数据绑定等内容。进一步查看找到了一个 WAService.js 文件。 查看 WAService.js 文件源码:

在代码最开始,跟 WAWebview.js 一样的 WeixinJSBridge 兼容模块然后是跟 WAWebview.js 一样的 Reporter 模块。比 WAWebview.js 中 wx 功能更为丰富 wx 接口模块。(剩余部分 wx api 都在这里)appServiceEngine 模块,提供 Page,App,GetApp 接口为 window 对象添加 AMD 接口 require define

综上,WAService.js 主要实现的功能:

App( ) 小程序的入口;Page( ) 页面的入口wx API;页面有的作用域,提供模块化能力数据绑定、事件分发、生命周期管理、路由管理

到这里我们得出结论,小程序的架构方案:

整个小程序由两个 webview 组成,代码分为 UI 层和逻辑层。UI 层运行在第一个 WebView 当中,执行 DOM 操作和交互事件的响应,里面是 WAWebview.js 代码及编译后的内容。逻辑层执行在(第二个webview 中)独立的 JS 引擎中(iOS:JAVAScriptCore, android:X5 JS解析器;统称 JSCore;开发工具中,nwjs Chrome 内核),WAService.js 代码和业务逻辑。

当我们对 view 层进行事件操作后,会通过 WeixinJSBridge 将数据传递到 Native 系统层。Native 系统层决定是否要用 native 处理,然后丢给 逻辑层进行用户的逻辑代码处理。逻辑层处理完毕后会将数据通过 WeixinJSBridge 返给 View 层。View 渲染更新视图。

架构的讨论

微信的这种架构,对逻辑和UI进行了完全隔离,小程序逻辑和UI完全运行在2个独立的Webview里面来处理。那么这么做的好处是啥?总感觉更加麻烦了。除了小程序外,还有人采用这种架构设计么?

在网上搜索了一下,目前使用这种架构的项目还真有一个:去哪儿最新的 YIS 框架

该项目做法和小程序十分类似,唯一缺少的就是没有 native 的组件吧。然而官方文档上也没有任何介绍,为什么要这么做,只是说更流畅了。

一些看法

传统 web 页面显示需要经历一下几个步骤:

webview 初始化加载 HTML, CSS, JS编译 JSRender 计算DOM Path

而利用小程序架构后,我们就可以将上述过程拆解成两部分并行执行: webview 部分:

webview 初始化加载 HTML,CSS, JS (经过拆分后,体积大幅度减小)编译 JS等待页面需要的数据反序列化数据执行 Patch渲染页面等待更多消息

jscore 部分:

初始化加载框架 js 代码编译 js加载业务逻辑 js 代码编译 js计算首屏虚拟 DOM 结构序列化数据,传输等待 webview 消息,或者 Native 消息

这样渲染进程和逻辑进程分离,并行处理:加速首屏渲染速度;避免单线程模型下,js 运算时间过长,UI 出现卡顿。 完全采用数据驱动的方式,不能直接操作 DOM,利用定制开发规范的方式避免低质量的代码的出现。

当然这种架构方案也有一定的缺点:

不能灵活操作 DOM,无法实现较为复杂的效果部分和 NA 相关的视图有使用限制,如微信的 scrollView 内不能有 textarea。页面大小、打开页面数量都受到限制需要单独开发适配,不能复用现有代码资源。在 jscore 中JS 体积比较大的情况下,其初始化时间会产生影响。传输数据中,序列化和反序列化耗时需要考虑希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)

关注 {我},享受文章首发体验!

每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

原文链接:http://eux.baidu.com/blog/fe/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%9E%B6%E6%9E%84%E5%8E%9F%E7%90%86

作者:田光宇

1.《微信小程序框架 微信小程序架构原理》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《微信小程序框架 微信小程序架构原理》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/keji/347257.html