内容涉及:
- 对于Page的WXML文件的编译和使用
- 对于Page的JS文件的编译
- 小程序的Page代码的加载
- 小程序的Page的实例化和首次渲染
- 小程序的Page的重新渲染
- 渲染层和逻辑层的双向通讯
- web和原生混合渲染
- uni-app的底层原理
小程序项目目录结构
-
微信小程序由一个App对象、多个Page对象组成。App对象,代表应用全局入口。Page代表视图,视图之间通过wx.navigateTo(’path’)跳转。一个Page至少由两个文件描述。WXML文件描述渲染,JS文件描述业务逻辑。
-
换言之,一个Page主要抽象成两部分:渲染逻辑、业务逻辑。可以说,所有Pages的WXML文件构成整个小程序的渲染层,所有Pages的JS文件构成整个小程序的业务逻辑层。现在这两层运行在不同线程上。
对于Page的WXML文件的编译和使用
- WXML是小程序描述渲染逻辑的标签语言。
- Exparser是小程序执行渲染逻辑的程序。
- Exparser接受WXML输出JS代码,输出的JS代码直接是Page的结构生成函数。这些编译好的函数代码,放在代码包里。到时候,哪个Page要显示,就执行对应的结构生成函数。这些函数执行,得到描述 Page dom结构和样式的 JSON。也就是说,运行时全权负责渲染的,就是这些结构生成函数。
结构生成函数 对应 动态的XML
- 因为WXML具有动态性,所以不直接把WXML编译成 JSON,而是编译成函数,函数再生成 JSON。这样,就获得了在运行时动态改变JSON结构的能力。
对于Page的JS文件的编译
- 所有Page的JS文件,会打包进一个JS文件。小程序的入口文件是app.js。当app.js打包完,小程序会按照在全局配置app.json中定义的pages列表项,逐一打包Page的JS文件,最终合成一个app-service.js,放进代码包。
小程序的Page代码的加载
- 第一次点开小程序的时候,作为宿主的微信客户端线程开始下载代码包(Page的业务逻辑app-service.js + Page的结构生成函数)。
- 与此同时开启两个js线程,一个带dom一个不带dom。带dom的叫webview,不带dom的叫jscore。代码下载下来后,交给他们执行。
- 不带dom的线程注入app-service.js,带dom的线程注入结构生成函数。
- 总而言之,在这个初始化阶段,加载基础库(Exparser等)后,jscore注入app-service.js、webview注入结构生成函数,为Page的实例化和渲染做好准备。
小程序的Page的实例化和首次渲染
- 小程序启动时会选取首页Page做实例化和渲染,其他Page的实例化和渲染,是在以后每次调用wx.navigateTo("path")时发生的。
- 调用wx.navigateTo时,新开一个webview线程,注入结构生成函数来加载,然后等待jscore线程的发号令。
- 与此同时在另一边,调用wx.navigateTo时,jscore线程要实例化Page(初始化组件函数和页面数据),实例化后jscore释放信号让webview的Exparser执行结构生成函数
- 当运行时用户跳转执行wx.navigateTo("path")时,path的结构生成函数注入新开的webview线程,执行它生成页面结构(虚拟dom),虚拟dom是普通JSON。虚拟dom交给Exparser的web渲染器使用dom进行渲染。
小程序的Page的重新渲染
- 以后Page实例中的数据变化了,需要重渲染,jscore线程再次请求webview线程执行结构生成函数。
- 结构生成函数输出虚拟dom(JSON),虚拟dom交给Exparser的web渲染器,渲染器使用diff算法进行DOM渲染。
渲染层和逻辑层的双向通讯
- 微信小程序中有webview线程在监听dom事件,dom事件触发时,事件最终会传给jscore线程让jscore线程执行事件函数。
- jscore线程在事件函数中执行完业务逻辑后执行setData,最终会把新data传给webview线程,webview线程中调用结构生成函数、调用渲染器执行渲染。
web和原生混合渲染
- Exparser是微信小程序使用的组件化框架,职责涵盖处理数据绑定、组件系统、事件系统、通信系统等一系列框架逻辑。在webview中实际调用结构生成函数、执行渲染的就是他。
- 微信为开发者提供了一些现成可以使用的Exparser组件,大部分是在webview中由DOM实现渲染的,但也有一小部分不由DOM实现渲染而是由原生实现渲染,这类组件称为“原生组件”。
- 原生组件的实现原理是,由webView渲染一个占位的空白区域,留出位置,再由原生API在相同位置渲染一层图像画面
以下为转载:
使用Vue进行小程序开发:uni-app的实现原理webpack、编译器、运行时
- webpack 。webpack是前端常用的一个模块打包器,uni-app构建过程中,会将Vue SFC的template、script、style三段式的结构,编译成小程序四段式结构,会得到xml、css、js、json四种文件。
- 编译器 。uni-app的编译器本质是把Vue 的视图编译成小程序的视图,即把template语法编译成小程序的wxml语法,之后,uni-app(Vue)不会存在视图层,视图层的部分完全交给小程序(Exparser)自身维护。 但是Vue的逻辑层还保留,那Vue跟小程序是怎么交互的呢?这就依赖于uni-app的运行时。
- 运行时 。uni-app运行时中的代理机制,打通了Vue和小程序。小程序视图层的更新,比如事件点击、触摸等操作,会经过uni-app的事件代理机制,触发 Vue的事件函数执行。而Vue的事件函数造成了数据更新,又会重新经过uni-app运行时,触发小程序的setData,进一步更新小程序的视图层。
Vue和小程序(Exparser)的通讯
Q:小程序视图层事件响应,会触发小程序逻辑层,逻辑层会调用vue相应的事件,触发数据更新。那Vue数据更新之后,又是怎样触发小程序视图层更新的呢?
A: 小程序视图层更新,必须使小程序逻辑层更新。小程序逻辑层更新必须要调用小程序的 setData 函数,而Vue数据更新的时候会触发Vue.prototype._update 方法,所以,只要在 _update 里调用 setData 函数就可以了。所以,uni-app在Vue里新增了这一逻辑。