基于Vue开发微信小程序和原生App – WOT2018演讲文字实录

大家,感谢51CTO提供平台,有机会来跟大家一起交流分享,这次和以前一样,依然是跨端的话题,只不过本次是《基于Vue开发微信小程序和原生App》。

今天演讲的内容主要包括三个部分:
– 第一部分:基于Vue开发微信小程序
– 第二部分:基于Vue开发App
– 第三部分:其它端覆盖的计划和思考

基于Vue开发微信小程序

首先是如何基于Vue开发微信小程序,目前业界已经有一些成熟方案,比如腾讯自己出的wepy,发布时间1年半,这是一个接近Vue开发风格的框架,支持组件 Props 传值,但wepy并没有实现完整的Vue开发体验;

而美团点评团队近期推出的mpvue,则实现了完整的Vue开发体验,因而后来居上,发布短短2月内,获得7000 star,目前的star已经过万,mpvue的开源地址及官网地址,参考PPT上链接地址。

我们在微信小程序端的解决方案,就是基于mpvue进行的完善,感谢美团点评前端团队!欢迎大家到github上给mpvue项目点star!

接下来,我会花一部分时间,讲一讲mpvue的主要特性及实现原理。

mpvue主要特性

使用 mpvue 开发小程序,你将在小程序技术体系的基础上获取到这样一些能力:

  • 彻底的组件化开发能力:提高代码复用性;小程序本身定位为一个简单的逻辑视图层框架,官方并不推荐用来开发复杂应用,但现实业务需求却难以做到精简。复杂的应用对开发方式有较高的要求,如组件和模块化,使用mpvue,将获得彻底的组件化开放能力。
  • 完整的 Vue.js 开发体验,熟悉Vue技术栈的前端,可以快速开发小程序。
  • 方便的 Vuex 数据管理方案:方便构建复杂应用
  • 快捷的 webpack 构建机制:自定义构建策略、开发阶段 hotReload
  • 支持使用 npm 外部依赖
  • 使用 Vue.js 命令行工具 vue-cli 快速初始化项目
  • H5 代码转换编译成小程序目标代码的能力

mpvue快速体验

通过 Vue.js 命令行工具 vue-cli,开发者只需在终端窗口输入几条简单命令,即可快速创建和启动一个带热重载、保存时静态检查、内置代码构建功能的小程序项目:

# 全局安装 vue-cli
$ npm install --global vue-cli

# 创建一个基于 mpvue-quickstart 模板的新项目
$ vue init mpvue/mpvue-quickstart my-project

# 安装依赖
$ cd my-project
$ npm install
# 启动构建
$ npm run dev

mpvue构建流程

建构流程是整个项目最核心的地方之一,通过webpack,完成将Vue的单文件模板 转换为 wxml 和 样式转换优化以及其他的若干代码的拼接压缩混淆等操作,最终使之可以运行在微信小程序的环境中。

大家看屏幕上的对比图,左侧为mpvue的项目结构,右侧为编译后的小程序项目结构,可以很清晰的看到:

  • 将mpvue中的App.vue,转化成了app.js/app.json/app.wxss三个文件
  • 将mpvue首页的index.vue,转化成了main.wxml/main.js/main.wxss三个文件

这种转化是如何实现的?这就是接下来要将的mpvue-loader的功能。

mpvue核心实现 – 编译器

mpvue-loader 是 vue-loader 的一个扩展延伸版,类似于超集的关系,除了 vue-loader 本身所具备的能力之外,它还会产出微信小程序所需要的文件结构和模块内容。

具体来说,mpvue-loader实现了如下功能:

  • 将Vue的单文件模板拆分为符合小程序规范的多文件结构,例如App.vue会生成app.js/app.json/app.wxss,其余的vue页面会生成对应页面的page.js/page.json/page.wxml/page.wxss文件。
  • 将Vue中的html模板标签,转化为小程序的wxml标签
  • 将Vue中的css部分,转化为符合小程序规范的wxss

mpvue-loader 是一个编译器,完成了Vue的单文件组件规范向小程序多文件规范的转换,实际运行中,Vue的数据是如何同小程序进行同步的?这是我们接下来要讲的mpvue最重要的实现部分,mpvue的runtime。

mpvue核心实现 – runtime

Vue.js 和小程序都是典型的逻辑视图层框架,大家知道,逻辑层和视图层之间的工作方式为:数据变更驱动视图更新;视图交互触发事件,事件响应函数修改数据再次触发视图更新。

Vue 和小程序有一致的工作原理,都具备数据绑定、事件系统。

mpvue作为中间桥梁,提供了一个运行时,打包到最终运行的小程序发行代码中,该运行时实现了Vue和小程序两系统之间的数据同步、事件同步以及生命周期管理。

具体来说,实现方式如PPT上原理图:
– mpVue将小程序的数据绑定功能,托管给了Vue;Vue 数据变更后,通过mpvue的数据同步机制将最新数据同步到小程序。
– 小程序负责视图层展示及用户交互,用户在小程序视图中触发点击、滚动等操作后,先触发小程序的事件函数,接着通过mpvue的事件代理机制,触发Vue的事件函数,因此业务逻辑同样收敛在Vue中;
– 小程序的生命周期,纳入Vue实例的生命周期中

这样,开发者就可以将精力聚焦在 Vue.js 上,参照 Vue.js 编写与之对应的小程序代码,也就实现了完整的Vue开发体验。

到目前为止,我们已经讲完了mpvue的主要原理及工作方式,也就讲清了基于Vue开发小程序的方式方法。

解下来,我们讲解如何基于Vue开发App。

基于Vue开发App

通过前半部分的讲解,我们知道,基于Vue开发的项目,通过mpvue的编译及运行时,已经可以在微信小程序上正常运行了。

那如何实现发布到App呢?

一个直观的思路就是,在App上模拟一套小程序一样的运行时环境。

接下来我们就讲讲小程序的运行时环境是怎样的,我们能否实现模拟,以及模拟的方案。

微信小程序的框架介绍

微信小程序框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

小程序框架的核心是一个响应的数据绑定系统。

整个小程序框架系统分为两部分:视图层(View)和逻辑层(App Service)。

视图层由 WXML 与 WXSS 编写,由组件来进行展示,最后由webview进行渲染。小程序有极好的用户体验,很多人以为小程序使用了原生渲染,实际上并不是,还是webview渲染,具体来说:

  • 是由 WKWebView 来渲染的,环境有 iOS8、iOS9、iOS10
  • 是由 X5 基于 Mobile Chrome 53/57 内核来渲染的

小程序逻辑层主要负责几大功能:
– 数据管理,逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
– 应用及页面生命周期管理,
– 提供丰富的 API,如扫一扫,支付等系统原生能力及微信特有能力。

开发者编写的所有JS代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。

小程序框架的逻辑层并非运行在浏览器中,而是在独立的JS引擎中,具体来说:

  • 在 iOS 上,小程序的 javascript 代码是运行在 JavaScriptCore 中
  • 在 Android 上,小程序的 javascript 代码是通过 X5 JSCore来解析并执行

我们以小程序中列表页面为例,讲一讲逻辑层和视图层的分工,列表数据是通过联网从服务器动态获取的,这个联网的代码虽然写在列表页的js中,但实际联网请求并不是在列表页的webview中发出,而是在逻辑层的JS引擎中发出,逻辑层获得网络响应后,改变数据,然后通知列表页webview进行渲染。

接下来,我们再细细拆分小程序框架的每个部分,看如何实现,我们知道小程序和Vue很多功能是类似的,因此我们在实现App运行时环境,目标是仅保留一套系统。

需要实现的引擎功能

如PPT图上所示,小程序的wxml实现了数据绑定、列表渲染、条件渲染等能力,而这些也是Vue的基础功能,因此我们的方案是将这些能力委托给Vue,放弃wxml。

引入Vue runtime后,回头再看小程序的运行时框架,我们目前可以拿掉的功能有:
– 数据绑定系统,完全使用Vue实现
– wxml

另外,wxss 实际上是在css子集基础上进行的少量扩充,实现比较简单,可以暂不考虑。

那剩下的只有组件管理、页面管理、原生API管理三大部分了,我们重点讲一讲组件管理及原生API实现。

小程序框架 – 基础组件

小程序提供了7大类基础组件,比如容器组件、表单组件、多媒体组件等。

对于基础组件,我们的思路是基于Vue的自定义组件封装,比如我们可以通过div封装一个view组件,并内置到运行时中。

对于包含特定业务的组件,例如navigator组件,也可以直接利用Vue已实现的router-link类模拟代替,不过需要拦截跳转逻辑,使用新webview打开,而不是当前页面跳转,从而实现窗口切换的原生动画。

小程序框架 – JS API

小程序框架提供了十几大类、几百个原生API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

并且这些API都是同时跨iOS、Android两端的,如果想从头模拟这些API实现,工作量是巨大的。

但对DCloud而言,这个却是容易实现的,因为我们早已实现了HTML5+ 规范,该规范归属于HTML5中国产业联盟,针对HTML5欠缺的设备及原生能力进行封装,历经4年的发展,早已实现了几百个原生API的封装,且经过数十万App的验证,稳定性毋庸置疑。

如PPT演示,二维码、原生地图、水平仪、加速器、分享、推送,这些功能都是通过HTML5+ 封装的JS实现的。

所以,我们的思路就是,将微信的API做一次封装,当运行在App引擎上时,实际执行的却是HTML5+ 的代码。

以wx.showToast为例,我们可以通过plus.nativeUI.toast方法来模拟执行,以plus开头的API就是HTML5+的JS定义。

这里的JS代码重写,有几个技术点,比如:
– 同步/异步封装,比如获取设备信息,小程序是异步回调中获取,但HTML5+却可以同步获取
– 参数封装,比如小程序的回调都有complete参数,但HTML5+基本只有success、fail两个参数

这些都需要注入前端框架去模拟实现。

跨端兼容方案 – 条件编译

我们可以将常用的组件、JS API封装到框架中,开发者按照规范开发即可保证快平台兼容,大部分业务均可直接满足。

但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况,这种情况下,我们还提供了条件编译机制,如PPT所示,开发者可以判断当前是微信平台的情况下,单独实现微信运动;当将代码发布成App时,这部分代码不会编译到最终代码中,可有效缩减发行资源的体积大小。

条件编译支持针对JS、CSS、组件进行编写。

至此,打通了发布到App的技术屏障,我们给这套方案起了个名字,叫它 uni-app ,简单画一个runtime示意图,如PPT所示:

  • 底层为iOS、Android系统
  • 中间为HTML5+ runtime(plus引擎)
  • 上层为数据绑定系统及JS API,数据绑定系统依赖Vue runtime,JS API通过uni2plus实现向HTML5+的转换

开发规范约定

为了实现微信小程序、原生App的跨端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:

  • 页面文件遵循 Vue 单文件组件 (SFC) 规范
  • 组件标签靠近微信小程序规范
  • 样式遵循小程序的wxss
  • 接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 uni
  • 平台特殊API,通过条件编译调用平台原生API
  • 数据绑定及事件处理靠近 Vue.js 规范,同时补充了App及页面的生命周期
  • 为兼容多端运行,建议使用flex布局进行开发

开发规范对比

对比表格读一下

周边配套

HBuilderX介绍

其它端的思考和计划

H5网站

  • 发布为单页应用
  • 复用App的UI组件
  • 使用vuex实现app.js中的全局参数
  • 模拟实现App/Page生命周期事件
  • 模拟API实现或空实现

其它动态类App

支付宝小程序、百度小程序和微信小程序类似,做部分替换即可,实现起来相对简单。

快应用完全是原生渲染,布局为flex布局,实现起来稍微复杂一点。