+```
+
+#### 复杂表达式 & filter
+
+可以在模版里面写复杂表达式、调用实例上的方法,当然也可以用更简洁的 filter 语法,跟平时用 Vue 开发一样。
+
+```html
+
+
{{ message.toUpperCase() }}
+
{{ toUpperCase( message ) }
+
{{ message | toUpperCase }}
+
+```
+
+#### v-html
+
+要使用 `v-html` 需要添加插件 `@megalo/vhtml-plugin`,并引入模版解析库 `octoparse`,在页面入口安装一下插件:
+
+```javascript
+import Vue from 'vue'
+import VHtmlPlugin from '@megalo/vhtml-plugin'
+
+Vue.use(VHtmlPlugin)
+```
+
+利用 `v-html` 指令然后就可以在小程序中渲染 html 了。
+
+```html
+
+```
+
+### 更好的数据更新性能
+
+小程序的官方明确说明,在调用 setData 更新数据时如果数据量过大或频率更高,会引发性能问题。megalo 在框架底层已经帮开发者对此进行优化,每次数据发生变化时,megalo 只会将视图中要展示的且发生变化的数据进行更新,将 setData 的数据更新量最小化,同时对更新数据频率进行了限制。
+
+像下面这段代码,如果视图只需要展示 `user.name` 这个字段的话,在进行数据同步时只会将 `user.name` 这个字符串更新到视图层,其余字段是不会同步到小程序的对象上的。
+
+```html
+
{{ user.name }}
+
+```
+
+### 支持更多平台
+
+今年以来,各大流量平台都在小程序领域有所动作,蚂蚁金服成立小程序事业部,百度、今日头条也纷纷推出自己的小程序。megalo 目前已经支持微信和支付宝小程序,百度小程序等平台的支持也在计划当中。
+
+
+
+
+
+
+## 使用
+
+使用 megalo 开发非常简单,只需在常见的 Vue 项目 webpack 构建配置上配置 `@megalo/target` 并引入 `@magalo/template-compiler` 即可。如果需要编译成支付宝小程序,只需要设置 `platform: 'alipay'`。
+
+```javascript
+const { createMegaloTarget } = require('@megalo/target');
+module.exports = {
+ target: createMegaloTarget( {
+ compiler: require('@megalo/template-compiler'),
+ platform: 'wechat'
+ } )
+ // 其他 webpack 配置,如 vue-loader 等
+};
+```
+
+接着,就可以像开发 Vue 应用一样去开发小程序。示例可以参考 [megalo-demo](https://github.com/kaola-fed/megalo-demo)。
+
+如果想用 typescript 进行开发,可以参考 [megalo-ts-simple](https://github.com/kaola-fed/megalo-examples/tree/master/ts-simple)。
+
+## 实现
+
+小程序在结构上主要有 Service(JavascriptCore) 和 View(WebView) 两部分组成(微信和支付宝小程序有着类似的结构,下文均以微信小程序为例,并简称为小程序),分别运行在独立的环境上,之间不具备共享数据通道,二者的通信方式是将数据封装在 js 脚本后传递。Page 实例就在 Service 中,通过 setData 方法将数据传递到 View。View 则通过事件绑定将视图层触发的事件传递给 Service。Service 层中无法操作视图层的 DOM 节点。
+
+
+
+
+
+实际开发中,小程序的逻辑和模版需要写在 .js 和 .wxml 两个文件中,分别在 Service 和 View 中执行。如果要将在浏览器端的 Vue 放到小程序中跑,需要将 .vue 文件中的 template 片段转换成 .wxml 文件,并对 Vue 的 runtime 部分改造,将其中的 DOM 操作移除,通过小程序的 Service 中的页面实例上的 API 与 View 进行通信。
+
+最终的运行效果是,当 Vue 的 vm 上数据发生更新时,会重新渲染出 vdom,在的 patch 阶段,框架不在去操作 DOM,而是通过 Page 上的 setData 方法将变化的数据更新到视图层,完成 Vue 和 小程序的视图更新,这就是 megalo 底层所做的工作。
+
+
+
+
+
+megalo 的实现,主要分成以下四个部分,下面本文将对每个部分进行介绍。
+
+### 生命周期
+
+小程序中,每一个页面(Page)是一个实例,页面的生命周期钩子有很多,但和实例创建的两个关键生命周期分别是 `onLoad` 和 `onReady`,它们分别在「`页面加载,实例初始化后`」和「`初次页面渲染完成`」时触发。Vue 的实例要和小程序实例建立起联系,则需要在小程序 Page 实例创建好以后,即在 `onLoad` 的钩子函数里,去初始化对应的 Vue 根实例,将页面实例 `page` 挂载到 Vue 实例的 `$mp` 上,此时也会触发 Vue 的生命周期钩子 `created`。在页面初次渲染完成后,则会调用 `$mount` 方法,与在浏览器中挂载 DOM 节点不同,这里会将 Vue 实例上的数据初始化到视图层中。由此,Vue 实例就与小程序的 Page 实例简历起了联系。
+
+
+
+
+
+除了这两个生命周期钩子以外,像小程序的 `onShow`、`onHide` 等生命周期钩子在触发时,也会尝试触发 Vue 实例上的同名钩子函数,实现两种实例间生命周期的绑定。在小程序页面退出销毁时,会触发 `onUnload` 钩子,此时 Vue 的实例也会跟着销毁。
+
+### 模版转换
+
+小程序有它特有的模版语法和文件名后缀,所以在构建阶段,我们会将 .vue 文件中的 template 部分提取出来并转换成对应的 .wxml 文件。标签名、语法都会进行相应的转换,如图所示。
+
+
+
+
+
+这一部分是在构建阶段完成的,这意味着,megalo 不支持 render 函数的写法。在构建阶段除了将模版转换成 .wxml 以外,还需要对模版中的每个节点进行转换,并在生产的 render 函数中加入相关的节点标记信息,数据映射和事件代理需要这些信息。
+
+### 数据映射
+
+由于无法直接操作视图层的 DOM,所以我们只能利用 page.setData 这个方法完成数据到视图层的映射。最简单暴力的方法,是将 Vue 实例上的所有数据统统收集起来,通过调用 page.setData 方法更新 Page 实例的数据,这个方法会将数据挂载到 Page 实例上,同时也会把数据传递给视图层。
+
+
+
+
+
+但是,这种粗暴的更新方式有两个弊端:
+
+i. 全量更新 VM 上的数据是无法区分哪些数据是视图层需要的,冗余无用的数据会被更新到 page 实例上。像下图这个例子,视图层只需要展现两个字符串,如果 vm 上还存在两个大数组,它们也会被无脑同步到 page 上。
+
+
+
+
+
+ii. 同步到 page 实例上的数据其实就是原始数据,并不是视图层实际要展示的数据,所以展示数据的格式化与转换需要依赖小程序模版的解析能力,导致一些 Vue 支持的模版语法无法支持,例如 filter、复杂表达式、传递 class 对象等。
+
+
+
+
+
+当然以上两个弊端不会对功能开发造成影响,但在实际的业务开发中,会让开发体验不一致,尤其是 h5 代码迁移到小程序时,对效率影响颇大。为了解决这个问题,megalo 采用另一中方式,即将 render 时生成的 vnode 上的数据更新到视图,vnode 的数据就是已经处理好的展示数据,根据 vnode 构造每个节点的数据结构,再同步到视图层。
+
+例如以下这段代码,在构建阶段 megalo 会对每个节点进行标记,使 render 时生成的 vnode 和模版中每个插值能够对应上。
+
+```html
+
+
+ {{ date | format( 'YYYY' ) }}
+
+
+
+
+ {{ node_1.text }}
+
+```
+
+以这种方式实现的数据映射,只有视图层需要的两个字符串数据会被同步到小程序的 Page 实例上,其余数据则被认为与视图无关则不会进行同步。
+
+```javascript
+export default {
+ data() {
+ return {
+ classObj: {
+ 'kaola': true
+ },
+ date: new Date(),
+ users: {
+ // big object
+ }
+ }
+ }
+}
+```
+
+如下图所示,Vue 渲染出来的 vnode 会被以特定的数据结构映射到 page 上,再同步到小程序视图层。
+
+
+
+
+
+以这种方式实现的数据映射,可以更好地支持 Vue 的模版语法,且更大限度地减少更新视图时传输的数据量,从框架层面规避 setData 的性能问题。
+
+### 事件代理
+
+小程序视图触发事件后,会将 event 对象通知到 Page 实例,那么我们只需要将视图层中所有的事件都代理到 page.proxy 这个方法中,然后再靠这个方法从 Vue 的实例树上找到对应的 vm 和 handler 做事件处理。为了实现这一目的,在构建阶段对模版进行编译时,除了要将事件监听方法转换为 `proxy` 以外,还需要通过 `data-` 在元素上标记对应的组件 `compid` 和节点 `nodeid`。
+
+```html
+
+
+
+
+
+```
+
+事件触发时,proxy 方法会从 event 对象上获取对应的 id 信息和事件类型,进而从 Vue 的根 vm 开始查找,最终在 vnode 上找到对应的 handler 并执行事件处理,完成小程序事件到 Vue 实例的事件代理。
+
+
+
+
+
+## 现在与未来
+
+目前,megalo 已经逐步在考拉的小程序应用开发中投入使用,但 megalo 的数据映射方案早已通过 mpregular 在考拉的大量小程序应用中得到了验证。现在,megalo 支持 typescript 开发,支持支付宝小程序。
+
+百度智能小程序的支持也在计划之内,同时,我们还计划开发一个兼容个平台的 UI 组件库、API 库,尝试将跨 H5 和各小程序平台的应用开发之间的差异最小化,提升开发效率。
+
+## github
+
+- [megalo](https://github.com/kaola-fed/megalo)
+- [megalo-demo 示例](https://github.com/kaola-fed/megalo-demo)
+- [megalo-aot 构建工具](https://github.com/kaola-fed/megalo-aot)
+- [megalo-examples 工程样例](https://github.com/kaola-fed/megalo-examples)
+
+## 参考
+
+- [mpvue](https://github.com/Meituan-Dianping/mpvue)
+- [小程序优化建议](https://developers.weixin.qq.com/miniprogram/dev/framework/performance/tips.html)
\ No newline at end of file