前言
小程序开发已成为Web端开发的重要组成部分,鉴于目前的业务需求,我们需要满足小程序的日常开发,此文用于记录小程序的基础开发摘要。
概述
小程序提供了一个简单、高效的应用开发框架和丰富的组件及API,帮助开发者在微信中开发具有原生 APP 体验的服务。小程序的底层原理应该是借鉴了vue的设计理念,采用mvvm模式的响应式编程。
差异性
小程序的主要开发语言是 JavaScript,网页开发渲染线程和脚本线程在小程序中是分开的,分别运行在不同的线程中。小程序的逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
小程序开发过程中需要面对的是三大操作系统 iOS 、Android、harmony 的微信客户端,以及用于辅助开发的小程序开发者工具,运行环境如下:
| 运行环境 | 逻辑层 | 渲染层 |
|---|---|---|
| iOS | JavaScriptCore | WKWebView |
| 安卓 | V8 | chromium定制内核 |
| 小程序开发者工具 | NWJS | Chrome WebView |
指南
代码构成
项目中会生成JSON配置文件、WXML模版文件、WXSS样式文件、JS脚本逻辑文件,以此来划分页面配置、UI模版、样式与业务逻辑。
- JSON配置:用于记录配置的静态文件:
app.json:小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等;project.config.json: 工具个性化配,例如界面颜色、编译配置、代码上传时自动压缩,云端存储,自动恢复;page.json:页面的个性化配置内容;
WXML模版:与.html相似的xml结构,使用微信封装的各种控件,例如:view、button、image、text等。WXSS样式:具备css的大部分特性,并做了扩充和修改。新增rpx尺寸样式以适配不同的设备屏幕。提供全局样式app.wxss与页面样式page.wxss。- JS逻辑交互:相应页面的各种事件、处理数据及逻辑显示,可以调用WX的各种封装API,例如:登录、本地存储、微信支付。
宿主环境
微信客户端即为宿主。
- 渲染层与逻辑层:页面的渲染由WebView进行渲染,多个页面则有多个WebView线程。逻辑层采用JSCore线程运行。线程通信都经由客户端中转,逻辑层的网络请求也Native转发,
- 程序与界面:客户打开小程序前,会把整个小程序的代码包下载到本地,注意这里只是主程序的相关代码。APP与页面都有自己的生命周期回调,请注意使用方式。
版本管理
-
不同版本的区别
- 开发版本:只保留每人最新的一份上传代码。可删除,不影响其他版本。
- 体验版本:选择某一开发版本作为体验版。
- 审核中版本:提交审核,且只能有一个份代码处于审核,重新提交可覆盖。
- 线上版本:线上用户使用的最新版。
-
发布上线:经过 预览-> 上传代码 -> 提交审核 -> 发布等步骤。
框架
逻辑层
-
behaviors:页面可以引用 behaviors ,用来让多个页面有相同的数据字段和方法。类似vue的mixin。 -
Component:主要用于复杂页面的拆分,有点像Flutter中闲鱼的拆分结构。
-
生命周期:微信的生命周期有点不同,需要双线程的通信处理。
-
路由:路由方式包括初始化、打开新的页面、重定向、页面返回、tab切换、重加载。Tab 切换遵从懒加载、root操作方式。 -
模块化:抽离共有js文件,通过module.exports或者exports才能对外暴露接口。在需要使用这些模块的文件中,使用require将公共代码引入。注意文件作用域,如需全局变量,可使用APP()存储。 -
API:小程序开发框架提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。-
监听
API:以on开头的 API 用来监听某个事件是否触发,如wx.onSocketOpen。 -
同步
API:以Sync结尾的 API 都是同步 API,如wx.setStorageSync。 -
异步
API: 大多数 API 都是异步 API,如wx.request。 -
Promise: 基础库2.10.2版本起,异步 API 支持 callback & promise 两种调用方式。这与vue中Promise的应用极为相似。
-
视觉层View
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示,将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
-
WXSS:css基础之上的一套样式语言。内容包括尺寸单位的适配规则、其他样式的导入、内联样式、选择器。 -
WXS: 小程序的自己的脚本语言,类似JS,内联在WXML中。为WXML提供丰富模板的数据预处理能力。本身不能处理自定义组件事件,只能响应内置组件的事件。 -
点击事件:事件是视图层到逻辑层的通讯方式。携带如 id, dataset, touches等信息。这诟病满满啊,传递要素过多,灵活性相比vue差太多。-
事件分类:冒泡与非冒泡,也就是透传的概念。
-
普通事件绑定:
bind:tap的属性为字符串,可以是可变数据。 -
阻止事件冒泡:
catch绑定会阻止向上冒泡。 -
互斥绑定:
mut-bind互斥是指冒泡过程中的mut-bind方法只执行一次。 -
事件捕获:触摸类事件支持捕获阶段,捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。采用
capture-bind、capture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。 -
事件对象:事件函数触发会接收到一个事件对象
type:事件类型,如tap等;timeStamp:事件生成时的时间戳,毫秒级;target:触发组件的属性值集合;- id:组件id
- dataSet:
data-开头的自定义属性组成的集合,编写用-,使用转驼峰写法;
currentTarget:响应组件的属性集合(冒泡会改变,同target);mark:事件标记数据;- 2.7.1以上使用;
- 冒泡路径上的所有mark都会被合并;
- 同名时,子覆盖父;
- 不会转换字符标记;
- 自定义组件中只包含组件内的mark;
detail:额外的信息;touches:触摸事件,当前停留在屏幕中的触摸点信息的数组;changedTouches:触摸事件,当前变化的触摸点信息的数组;
-
响应事件:为降低逻辑层与视图层的频繁交互,wx提倡使用
wxs在视图层完成数据及UI处理。 -
双向绑定:同
vue有model:value简单绑定,数据处理后更新需要this.setData({ value: 'leaf' })的写法。组件需要借助Component中的properties属性。 -
基础组件:框架为开发者提供了一系列基础组件. -
节点信息:节点信息查询API可以用于获取节点属性、样式、在界面上的位置等;节点布局相交状态API可用于监听两个或多个组件节点在布局位置上的相交状态。
-
显示区域:改变显示区域的尺寸的方法有支持屏幕旋转、启动大屏模式。
-
分栏模式:小程序提供在较大屏幕的分栏显示。
-
初始渲染:
- 逻辑层与视图层分别初始化。
- 可以启动初始化缓存,提前渲染页面。
- 初始化渲染只能使用内置组件。
- 可动态配置初始化渲染。
-
运行时
运行环境
微信小程序运行在多种平台上,不同运行环境下,脚本执行环境以及用于组件渲染的环境是不同的,性能表现也存在差异;平台间存在差异性,建议开发完成在各端检查。
JavaScript 支持
- 不支持动态执行JS代码,不支持创建函数;
- 内置
core-js,提高ECMAScript标准兼容性,但无法抹平,如async/await时,需要借助 代码转换工具 来支持这些语法。 - 避免使用
Proxy对象。 Promise时序在iOS环境下存在差异。
运行机制
- 生命周期:小程序从启动到最终被销毁,会经历很多不同的状态。
- 启动:分为冷启动与热启动。
- 前后台:展示给用户为前台,退出为后台。
- 挂起:后台后5秒停止JS运行,常驻功能会持续运行,如音乐、地理位置。
- 销毁:长时间未使用嚯资源紧张会销毁小程序。
- 冷启动与热启动:有自己的一套规则和配置。
- 退出状态:销毁前会调用
onSaveExitState用于保存一些数据状态。
更新机制
微信客户端会有若干个时机去检查本地缓存的小程序有没有新版本,并进行小程序的代码包更新。
-
启动时同步更新:在以下情况下,小程序启动时会同步更新代码包。同步更新会阻塞小程序的启动流程,影响小程序的启动耗时。
-
定期检查:微信运行时,会定期检查最近使用的小程序是否有更新。如果有更新,下次小程序启动时会同步进行更新,更新到最新版本后再打开小程序,尽可能保证用户能够尽快使用小程序的最新版本。
-
长时间未使用:为保障小程序版本的实时性,会强制同步检查版本更新,更新到最新版本后再打开小程序。
-
弱网、下载失败仍会启动旧的版本。
-
-
启动时异步更新:启动前未发现更新,小程序每次冷启动时,都会异步检查是否有更新版本。如果发现有新版本,将会异步下载新版本的代码包。但当次启动仍会使用客户端本地的旧版本代码,即新版本的小程序需要等下一次冷启动才会使用。
- 开发者可以使用
getUpdateManagerAPI手动触发,重启小程序。
- 开发者可以使用
-
小程序后台设置:
- 优先使用本地设置:无需强制用户同步更新到最新版本,优先使用本地版本,异步下载最新代码包。
- 最低可用版本:设置后同步检查本地低于该版本,则无法打开,并尝试下载最新版本,更新后会重新小程序。
自定义组件
介绍
页面内的功能模块抽象成自定义组件
- 将组件内
.json中声明component为true。 - 组件中
.wxss中不应使用ID选择器、属性选择器和标签名选择器。 - 组件中
.js中声明Component构造器。 - 使用组件在
.json中的usingComponents设定。 - 创建组件后,如出现找不到
.wxml,请清除缓存。
模版与样式
- 组件模版
- 组件模板的写法与页面模板相同。
- 组件模板中可以提供
<slot>节点,用于承载引用位置的子节点。
- 数据绑定
- 可以使用数据绑定,动态传递。
- 组件内的
wxss只对组件负责. - 样式隔离:
styleIsolation可指定样式隔离逻辑。wxss要避免使用标签名选择器。
- 外部样式使用
externalClasses。 - 样式中添加
~用来引用页面样式或父组件样式。 - 使用
virtualHost来构建虚拟节点,拒绝父类的设定。
Component 构造器
- 构造器时可以指定组件的属性、数据、方法等。
- 可以用来构造页面,并使用
behaviors来提取所有页面中公用的代码段。
通信与事件
- 组件通讯方式
WXML数据绑定:父控件向子控件指定数据。- 事件:子控件向父控件传递任意值。
- 父控件通过
this.selectComponent方法获取子组件实例对象,访问数据、方法。
- 监听事件:可以监听自定组件的触发事件,如
bindmyevent和bind:myevent。 - 触发事件:使用
triggerEvent指定事件名、detail对象和事件选项。 - 获取组件实例:通过
selector,如:this.selectComponent(".my-component")
生命周期
组件的生命周包括以下回调,另外所在页面的生命周期强相关,在pageLifetimes定义。
created:创建时执行。attached:进入页面节点。ready:视图层布局完成。moved:组件被移动到另外一个节点。detached:从页面节点移除。error:组件执行出错抛出。
behaviors
类似vue中mixins的特性,用于抽离共同属性、数据和方法。
- 使用需
require引用,组件behaviors添加引用方法名。 - 覆盖组合规则:
- 属性和方法:主覆盖引,后覆盖前。
- 数据字段:同类合并,主覆盖引,后覆盖前。
- 生命周期与
observer调用:按主顺序,先引后主,先前后后。
- 内置
behavior:自定义组件可以通过引用内置的behavior来获得内置组件的一些行为。
组件间关系
- 定义组件关系:可以添加
relations字段用关系组件的调用。 - 关联一类组件:使用
Behavior作为子控件共有内容,在relations使用Behavior代替组件路径作为关联节点。
数据监听器
数据监听器可以用于监听和响应任何属性和数据字段的变化,类似vue中的计算属性。
- 使用
observers描述监听属性与处理方法。
observers: {
'numberA, numberB': function(numberA, numberB) {
// 在 numberA 或者 numberB 被设置时,执行这个函数
this.setData({
sum: numberA + numberB
})
}
}
- 可以监听子数据段,还可以使用
**通配符批量匹配。
纯数据字段
纯数据字段是一些不用于界面渲染的 data 字段,可以用于提升页面更新性能。
- 使用
pureDataPattern匹配纯数据字段。 - 属性也可以创建纯数据字段,但不可用于
WXML及监听属不执行。 - 使用
数据监听器可以监听纯数据字段。
抽象节点
支持建立抽象的节点,由调用位置确定具体的插入组件的具体类型,可以提供默认组件类型。
自定义组件扩展
行文习惯
- 内部方法建议以下划线开头。
常用枚举集合
-
返回来源信息的场景:用来描述用户进入小程序的路径,可通过onLaunch和onShow,或wx.getLaunchOptionsSync中获取上述场景值。 -
热启动场值:若启动的场景中不带 path,则保留上次的浏览的状态.