小程序运行环境
运行环境 | 逻辑层 | 渲染层 |
---|---|---|
iOS | JavaScriptCore | WKWebView |
安卓 | V8 | chromium定制内核 |
小程序开发者工具 | NWJS | Chrome WebView |
需要注意到,小程序运行的三个环境,其底层 执行 JavaScript 与 渲染标记(DOM) 的引擎都不一样。具体那些地方不一样,现在或者将来或许我们都不能仔细去比对,能做的或许就是在实际开发中进行测试。
小程序宿主环境
就像网页开发,js 脚本的宿主环境是浏览器一样,小程序的宿主环境就是微信客户端,因此小程序可以调用微信提供的能力,这类似于微信发布的网页开发工具包 JS-SDK
,使得网页开发也能使用微信的能力。
通信模型
小程序有两种线程,一种是 WebView 线程,负责界面的渲染,一种是 JsCore 线程,负责执行 js 脚本。而一个小程序示例会存在多个界面,因此存在多个 WebView 线程。
这两种线程的通信由微信客户端(Native)做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型下图所示。
程序
小程序通过 app.json
来配置页面:
1 | { |
pages 数组中第一个默认为小程序首页。
小程序在微信中初始化完成后调用 onLaunch
:
1 | App({ |
启动小程序过程如图:
小程序只有一个 app 实例,由所以页面共享,因此 app 中的配置同时作用于所有页面,例如:自定义组件,样式等。
页面
小程序由多个页面组成,页面通过构造函数 Page
来注册页面:
1 | Page({ |
组件
一个页面由多个组件构成(类似于 html 标签,但是还是统一称作组件),组件的使用于 html 标签使用大体一致。
API
API 提供的就是微信的能力,例如获取用户信息、微信支付等等,API 大多是异步,因此处理异步问题在小程序中很常见。
小程序代码构成
小程序项目文件类型有多达五种:.wxml .wxss .json .js .wxs
。
.wxml
提供结构(html).wxss
提供样式(css).json
提供配置.js
提供交互逻辑.wxs
js 脚本,可通过<wxs>
组件引入,类似<script>
标签
而一个页面或者自定义组件均由以上 5 中文件组成。根据实际情况 .wxss .json .wxs
可不用。
数据驱动
我们知道,网页开发的交互逻辑都是通过 JavaScript
来操作 DOM
来完成;但小程序 JavaScript
脚本运行在 JavaScriptCore
(IOS) 或 JsCore
(安卓) 中,它们是不包含 BOM
和 DOM
对象的,因此小程序是不能像网页开发一样,直接操作 DOM
节点,这将带来诸多限制。
那我们要如何更新 UI 呢?这就需要理解数据驱动的概念,当前 React Vue
等框架均是采用这种方式来实现 UI
与数据的绑定,通过 JavaScript
来改变数据从而更新 UI
。
WXML结构实际上等价于一棵Dom树,通过一个JS对象也可以来表达Dom树的结构,如图:

WXML可以先转成JS对象,然后再渲染出真正的Dom树,回到“Hello World”那个例子,我们可以看到转换的过程如图:

这时,如果 JavaScript
将 WXML 的 JS 对象改变了,则:

这就是数据驱动UI,因此,小程序的界面渲染如图:

数据传递
页面与页面的数据传递
- app 实例
通过getApp()
全局接口,可以在小程序初始化后任何地方获取小程序实例的引用。通过操作app
实例的属性做到页面与页面之间的数据共享。
适合一些不需要缓存的,一次性的状态数据。
本地缓存
通过wx.setStorage/wx.getStroage
来操作需要缓存的数据,实现页面与页面之间的数据共享。服务器存储
通过调用后端接口来实现对用户配置或状态的数据进行存储,实现页面与页面之间的数据共享。
适合同一用户跨平台、跨终端的数据共享
页面与组件
通过 setData
和 模版数据绑定(数据驱动概念)来实现数据传递
组件与组件
- 父组件 -> 子组件:属性
- 子组件 -> 父组件:事件
允许传递的数据类型
因为小程序使用了模版,限于 JSON
字符串化规则,数据中不能包含 function symbol
以及循环引用。
TIP: 通过抽象节点节点的方式,可像自定义组件中传递一个组件。
与 React 的差异
个人决定小程序与React本质上都是已组件化的思想来组织代码,从而构建易维护、可重用的代码;都采用了 diff 算法来优化 DOM 渲染性能。但因小程序使用模版引擎,React使用JSX语法,
- 小程序组件通信上有组多限制,例如:无法传递函数,无法直接传递组件,没有高阶组件,模版中循环,if 判断不如 js 优雅等。但模版引擎的有点在于可以通过一些特定的指令(例如: bind:tap catch:tap capture-bind:tap)可帮助开发人员快速开发。
- React 通过JSX,DOM 结构直接表示为 JS 对象,因此 React 能够利用js语言的各种能力,几乎没有限制。但没有限制带来了强大能力的同时也带来了开发者架构负担。
小程序开发过程中遇到的问题
社区生态目前还太弱小,基本都要自己造轮子
小程序是否分包需要在一开始构建目录时就确定好,因为分包不是按配置,而是按目录,不智能
小程序是双线程工作,因此需要处理异步问题,但其本身虽然支持了 es6 语法,但不能成功编译成 es5,例如: async wait。需要自己解决
小程序使用了一部分原生组件,但当原生组件与非原生组件都绑定事件时,从原生组件冒泡到非原生组件在真机上的路径不确定,每次不一致
小程序事件通过DOM传递的数据存在大小写问题(如果命名包含了大写,事件对象中都是小写)
小程序文件上传其实是图片上传,参数 Header 配置的 content-type ,是无法成为后端接口请求的 content-type,实际上,后端接口的 header 可能是微信固定配置的 ‘image/jpg’
getMenuButtonBoundingClientRect偶尔获取不到值 。目前可以加延迟 100ms 或者 发现拿到异常值再重新获取