微信小程序开发指南

序言

小程序是什么

        小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验。

发展史

        小程序并非凭空冒出来的一个概念。当微信中的 WebView 逐渐成为移动 Web 的一个重要入口时,微信就有相关的 JS API 了。

1
2
3
4
5
6
7
8
9
10
WeixinJSBridge.invoke('imagePreview', {
current: 'http://inews.gtimg.com/newsapp_bt/0/1693121381/641',
urls: [ // 所有图片的URL列表,数组格式
'https://img1.gtimg.com/10/1048/104857/10485731_980x1200_0.jpg',
'https://img1.gtimg.com/10/1048/104857/10485726_980x1200_0.jpg',
'https://img1.gtimg.com/10/1048/104857/10485729_980x1200_0.jpg'
]
}, function (res) {
console.log(res.err_msg)
})

        以上是一个调用微信原生组件浏览图片的JS API,相比于额外引入一个JS图片预览组件库,这种调用方式显得非常简洁和高效。
        实际上,微信官方是没有对外暴露过如此调用的,此类 API 最初是提供给腾讯内部一些业务使用,很多外部开发者发现了之后,依葫芦画瓢地使用了,逐渐成为微信中网页的事实标准。2015年初,微信发布了一整套网页开发工具包,称之为 JS-SDK,开放了拍摄、录音、语音识别、二维码、地图、支付、分享、卡券等几十个API。给所有的 Web 开发者打开了一扇全新的窗户,让所有开发者都可以使用到微信的原生能力,去完成一些之前做不到或者难以做到的事情。

        使用 JS-SDK 调用图片预览组件

1
2
3
4
5
6
7
8
9
10
11
wx.previewImage({
current: 'https://img1.gtimg.com/10/1048/104857/10485726_980x1200_0.jpg',
urls: [ // 所有图片的URL列表,数组格式
'https://img1.gtimg.com/10/1048/104857/10485731_980x1200_0.jpg',
'https://img1.gtimg.com/10/1048/104857/10485726_980x1200_0.jpg',
'https://img1.gtimg.com/10/1048/104857/10485729_980x1200_0.jpg'
],
success(res) {
console.log(res)
}
})

JS-SDK 解决了移动网页能力不足的问题,通过暴露微信的接口使得 Web 开发者能够拥有更多的能力,然而在更多的能力之外,JS-SDK 的模式并没有解决使用移动网页遇到的体验不良的问题。用户在访问网页的时候,在浏览器开始显示之前都会有一个的白屏过程,在移动端,受限于设备性能和网络速度,白屏会更加明显。微信官方把很多技术精力放置在如何帮助平台上的Web开发者解决这个问题。因此微信官方设计了一个 JS-SDK 的增强版本,其中有一个重要的功能,称之为“微信 Web 资源离线存储”。

1
2
微信 Web 资源离线存储是面向 Web 开发者提供的基于微信内的 Web 加速方案。
通过使用微信离线存储,Web 开发者可借助微信提供的资源存储能力,直接从微信本地加载 Web 资源而不需要再从服务端拉取,从而减少网页加载时间,为微信用户提供更优质的网页浏览体验。每个公众号下所有 Web App 累计最多可缓存 5M 的资源。

        然而,页面切换的生硬和点击的迟滞感还是会给开发者带来不好的体验,微信官方希望能够给出:

  • 快速的加载
  • 更强大的能力
  • 原生的体验
  • 易用且安全的微信数据开放
  • 高效和简单的开发
            因此,微信小程序就诞生了。

小程序与普通网页开发的区别

相似点:主要开发语言是 JavaScript;

不同点:

小程序的网页开发渲染线程和脚本线程是双线程分离的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
双线程

网页开发面临各式各样的浏览器,PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对Safari、Chrome以及 iOS、Android 系统中的各式 WebView ,小程序面临的是两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具。
        在开发的过程中会经常发现,为什么我在(开发工具上)是好的,在我的(安卓手机)上也是好的,到你的(苹果手机)上就不好使了呢?
        因为,三个开发环境也是有很大差异的。

运行环境 逻辑层 渲染层
iOS JavaScriptCore WKWebView
安卓 V8 chromium定制内核
小程序开发者工具 NWJS Chrome WebView

开发流程,网页开发者在开发网页的时候,只需要使用到浏览器,并且搭配上一些辅助工具或者编辑器即可。小程序的开发则有所不同,需要经过申请小程序帐号、安装小程序开发者工具、配置项目等等过程方可完成。

小程序技术选型

渲染技术

        现在通用的渲染技术有:web渲染、Native渲染、web与Native混合渲染也就是Hybrid渲染。
        小程序选择了 Hybrid 的渲染方式,可以用一种近似 Web 的方式来开发,并且还可以实现在线更新代码。同时,引入原生组件有以下好处:

扩展 Web 的能力。比如像输入框组件(input, textarea)有更好地控制键盘的能力
体验更好,同时也减轻 WebView 的渲染工作
绕过 setData、数据通信和重渲染流程,使渲染性能更好

基础库

        小程序的基础库是 JavaScript 编写的,它可以被注入到渲染层和逻辑层运行。主要用于:

在渲染层,提供各类组件来组建界面的元素
在逻辑层,提供各类 API 来处理各种逻辑
处理数据绑定、组件系统、事件系统、通信系统等一系列框架逻辑
        由于小程序的渲染层和逻辑层是两个线程管理,两个线程各自注入了基础库。小程序的基础库不会被打包在某个小程序的代码包里边,它会被提前内置在微信客户端。这样可以:

降低业务小程序的代码包大小
可以单独修复基础库中的 Bug,无需修改到业务小程序的代码包

Exparser 框架

        Exparser 是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各种组件提供基础的支持。小程序内的所有组件,包括内置组件和自定义组件,都由 Exparser 组织管理。Exparser 特点包括:

基于 Shadow DOM 模型:模型上与 WebComponents 的 ShadowDOM 高度相似,但不依赖浏览器的原生支持,也没有其他依赖库;实现时,还针对性地增加了其他 API 以支持小程序组件编程。
可在纯 JS 环境中运行:这意味着逻辑层也具有一定的组件树组织能力。
高效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺寸也较小。

小程序基础

目录结构

        上图为微信小程序的项目结构,pages下面包含了小程序中的每一个页面,每一个页面由页面结构,页面样式,页面配置和逻辑代码四部分组成。

  • 页面结构
    页面结构文件为index.wxml,通过微信自定义的标签来写。
  • 页面逻辑
    页面逻辑通过JavaScript来书写。
  • 页面样式表
    类似CSS文件,来定义页面内元素的样式。
  • 页面配置
    页面内的权限等配置信息。

程序与页面

        当小程序准备加载的时候,微信会把整个小程序的代码包下载到本地。
紧接着通过 app.json 的 pages 字段就可以知道你当前小程序的所有页面路径:

1
2
3
4
5
6
{
"pages": [
"pages/index/index",
"pages/logs/logs"
]
}

        这个配置说明在 当前项目定义了两个页面,分别位于 pages/index/index 和 pages/logs/logs。而写在 pages 字段的第一个页面就是这个小程序的首页(打开小程序看到的第一个页面)。
        再接着,微信客户端就把首页的代码装载进来,通过小程序底层的一些机制,就可以渲染出这个首页。
        小程序启动之后,在 app.js 定义的 App 实例的 onLaunch 回调会被执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
App({
onLaunch() {
// 小程序启动之后 触发
},
onShow(options) {
// 页面出现的时候触发
},
onHide() {
// 页面隐藏的时候触发.
},
onError(msg) {
// 页面出错的时候触发
},
globalData: '这是全局的数据'
})

        整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp 方法获取到全局唯一的 App 示例,获取App上的数据或调用开发者注册在 App 上的函数。

1
2
3
// logs.js
const appInstance = getApp()
console.log(appInstance.globalData) // 这是全局的数据

组件

基础组件

1
<map></map>

原生组件

1
<video></video>

自定义组件

1
<my-component></my-component>

API

        微信官方提供了大量的 小程序的API 供开发者使用。

1
2
3
4
5
6
// 微信扫一扫
wx.scanCode({
success: (res) => {
console.log(res)
}
})

小程序发布

小程序发布多态

权限 说明
开发版本 使用开发者工具,可将代码上传到开发版本中。 开发版本只保留每人最新的一份上传的代码。 点击提交审核,可将代码提交审核。开发版本可删除,不影响线上版本和审核中版本的代码。
体验版本 可以选择某个开发版本作为体验版,并且选取一份体验版。
审核中版本 只能有一份代码处于审核中。有审核结果后可以发布到线上,也可直接重新提交审核,覆盖原审核版本。
线上版本 线上所有用户使用的代码版本,该版本代码在新版本代码发布后被覆盖更新。

小程序发布过程

简而言之:

1
2
3
a.预览 --> b.上传代码 --> c.提交审核 --> d.发布
# (开发者工具a.b.)
#(后台c.d.)

https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/release.html#%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%9A%84%E7%89%88%E6%9C%AC

小程序WXML的一些姿势

姿势们

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 简单用法 -->
<view>hello world!</view>

<!-- 变量绑定 -->
<view>{{ variable }}</view>

<!-- 动态渲染 -->
<view>{{ areUOk ? 'fine' : 'bad' }}</view>

<!-- 条件渲染 -->
<view wx:if="{{ people > 6 }}">拍皮球</view>
<view wx:elif="{{ 2 < people < 6 }}">撸串</view>
<view wx:else>加班</view>

<!-- 列表渲染 -->
<view wx:for="{{ list }}">...</view>

<!-- 模板 -->
<template name="muban"></template>

引入
import
include 两种方法
!!!此处有大坑,import方法不具备递归功能, A import B ,B 中 import C,但是A就无法使用C辽!!!

属性们

属性名 类型 描述 注解
id String 组件的唯一标识 整个页面唯一
class String 组件的样式类 在对应的 WXSS 中定义的样式类
style String 组件的内联样式 可以动态设置的内联样式
hidden Boolean 组件是否显示 所有组件默认显示
data-* Any 自定义属性 组件上触发的事件时,会发送给事件处理函数
bind/catch EventHandler 组件的事件 bind冒泡,catch不冒泡

小程序wxss的一些姿势

特殊的单位 rpx (responsive pixel)

        目的是更多型号的手机屏幕可以展示差不多的样式,如果用了px,就可能在大屏幕下过多留白,小屏幕下过于拥挤。
        小程序编译后,rpx会做一次px换算。换算是以375个物理像素为基准,也就是在一个宽度为375物理像素的屏幕下,1rpx = 1px。
        举个栗子:iphone6是375px宽度,也就是750物理像素,这个时候对应的rpx就是
        1rpx = 375 / 750 = 0.5px

微信rpx

使用wxss

        常规:按照上面目录结构当中的方式,是无需重复引用style文件的,直接定义直接用;
        骚操作:在wxss文件中使用@import

1
2
// index.wxss
@import url('./logs.wxss')

内联样式:不用多说的

1
<textarea style="{{ font-size: 24rpx; }}"></textarea>

小程序Js的一些姿势

闲话

可能在很多开发者的眼中,JavaScript 和 ECMAScript 是等价的,然而,其实这两者还是有很大不同的:
JavaScript是ECMAScript的实现形式。

在浏览器中

浏览器中的JavaScript    
ECMAScript BOM DOM

在node环境中

node中的JavaScript    
ECMAScript NPM NATIVE

在小程序中

小程序中的JavaScript    
ECMAScript 小程序的View 小程序的API

小提示

        由于小程序能够运行的环境较多,有IOS、安卓、小程序开发工具,在同一个平台上也会有不同的系统版本,这会导致部分ES6的代码不能够在机型上完美兼容,这个时候,只要在IDE中开启,ES6转ES5即可!

作者: 张熠
文章链接: https://crazyoctopusdan.github.io/2019/04/08/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.