微信小程序的版本

一般的软件开发流程是:开发者编写代码并自测开发版程序,直到程序达到一个稳定可体验的状态时,开发者会把这个体验版本给到产品经理和测试人员进行体验测试,最后修复完程序的 Bug 后发布,供外部用户正式使用。微信小程序的版本根据这个流程设计了微信小程序版本的概念,如表5-3所示。

表5-3 微信小程序的版本

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

考虑到项目是协同开发的模式,一个微信小程序可能同时由多个开发者进行开发,往往开发者在微信小程序开发者工具上编写完代码后需要到手机进行真机体验,所以每个开发者拥有自己对应的一个开发版本。因为处于开发中的版本是不稳定的,开发者随时会修改代码覆盖开发版,为了让测试和产品经理有一个完整稳定的版本可以体验测试,微信小程序平台允许把其中一个开发版本设置成体验版,因此建议在项目开发阶段特殊分配一个开发角色,用于上传稳定可供体验测试的代码,并把他上传的开发版本设置成体验版。

协同工作

如果你只是一个人开发微信小程序,可以暂时先跳过这部分,如果是一个团队需要先了解一些概念。

多数情况下,一个团队多人同时参与同一个微信小程序项目,每个角色所承担的工作或者权限不一样,中大公司的分工更为仔细。为了更形象的表达团队不同角色的关系以及权限的管理,我们通过虚拟一个项目成员组织结构来描述日常如何协同合作完成一个微信小程序的发布,组织关系如图5-1所示。

img ​ 图5-1 虚拟微信小程序项目组

项目管理成员负责统筹整个项目的进展和风险、把控微信小程序对外发布的节奏,产品组提出需求,设计组与产品讨论并对需求进行抽象,设计出可视化流程与图形,输出设计方案。开发组依据设计方案,进行程序代码的编写,代码编写完成后,产品组与设计组体验微信小程序的整体流程,测试组编写测试用例并对微信小程序进行各种边界测试。项目一般的成员构成与工作流程如图5-2所示。

img ​ 图5-2 提需求到发布微信小程序的流程

微信小程序成员管理

微信小程序成员管理包括对微信小程序项目成员及体验成员的管理。

  • 项目成员:表示参与微信小程序开发、运营的成员,可登录微信小程序管理后台,包括运营者、开发者及数据分析者。管理员可在“成员管理”中添加、删除项目成员,并设置项目成员的角色。

  • 体验成员:表示参与微信小程序内测体验的成员,可使用体验版微信小程序,但不属于项目成员。管理员及项目成员均可添加、删除体验成员。

不同项目成员拥有不同的权限,从而保证微信小程序开发安全有序。

权限 运营者 开发者 数据分析者
开发者权限
体验者权限
登录
数据分析
微信支付
推广
开发管理
开发设置
暂停服务
解除关联公众号
腾讯云管理
微信小程序插件
游戏运营管理

各权限功能说明

  • 开发者权限:可使用微信小程序开发者工具及开发版微信小程序进行开发
  • 体验者权限:可使用体验版微信小程序
  • 登录:可登录微信小程序管理后台,无需管理员确认
  • 数据分析:使用微信小程序统计模块功能查看微信小程序数据
  • 微信支付:使用微信小程序微信支付(虚拟支付)模块
  • 推广:使用微信小程序流量主、广告主模块
  • 开发管理:微信小程序提交审核、发布、回退
  • 开发设置:设置微信小程序服务器域名、消息推送及扫描普通链接二维码打开微信小程序
  • 暂停服务设置:暂停微信小程序线上服务
  • 解除关联公众号:可解绑微信小程序已关联的公众号
  • 微信小程序插件:可进行微信小程序插件开发管理和设置
  • 游戏运营管理:可使用小游戏管理后台的素材管理、游戏圈管理等功能

需要留意,项目管理者控制整个微信小程序的发布、回退、下架等敏感操作,不应把敏感操作的权限分配给不相关人员

API

为了让开发者可以很方便地调起微信提供的能力,例如获取用户信息、微信支付等等,微信小程序提供了很多 API 给开发者使用。

要获取用户的地理位置时,只需要:

wx.getLocation({
  type: 'wgs84',
  success: (res) => {
    var latitude = res.latitude // 纬度
    var longitude = res.longitude // 经度
  }
})

调用微信扫一扫能力,只需要:

wx.scanCode({
  success: (res) => {
    console.log(res)
  }
})

需要注意的是:多数 API 的回调都是异步的,你需要处理好代码逻辑中的异步问题。

更多的 API 能力请参考微信小程序的 API。

通过这个章节,你已经大概了解了微信小程序运行的一些基本概念。当你开发完一个微信小程序之后,就需要发布你的微信小程序。在下个章节,你会知道发布前需要做什么准备。

组件

微信小程序提供了丰富的基础组件给开发者,开发者可以像搭积木一样,组合各种组件拼合成自己的微信小程序。

就像 HTMLdiv, p 等标签一样,在微信小程序里边,你只需要在 WXML 写上对应的组件标签名字就可以把该组件显示在界面上,例如,你需要在界面上显示地图,你只需要这样写即可:

<map></map>

使用组件的时候,还可以通过属性传递值给组件,让组件可以以不同的状态去展现,例如,我们希望地图一开始的中心的经纬度是广州,那么你需要声明地图的 longitude(中心经度) 和 latitude(中心纬度)两个属性:

<map longitude="广州经度" latitude="广州纬度"></map>

组件的内部行为也会通过事件的形式让开发者可以感知,例如用户点击了地图上的某个标记,你可以在 js 编写 markertap 函数来处理:

<map bindmarkertap="markertap" longitude="广州经度" latitude="广州纬度"></map>

当然你也可以通过 style 或者 class 来控制组件的外层样式,以便适应你的界面宽度高度等等。

更多的组件可以参考 微信小程序的组件。

程序与页面

微信客户端在打开微信小程序之前,会把整个微信小程序的代码包下载到本地。

紧接着通过 app.jsonpages 字段就可以知道你当前微信小程序的所有页面路径:

{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ]
}

这个配置说明在 QuickStart 项目定义了两个页面,分别位于 pages/index/indexpages/logs/logs。而写在 pages 字段的第一个页面就是这个微信小程序的首页(打开微信小程序看到的第一个页面)。

于是微信客户端就把首页的代码装载进来,通过微信小程序底层的一些机制,就可以渲染出这个首页。

微信小程序启动之后,在 app.js 定义的 App 实例的 onLaunch 回调会被执行:

App({
  onLaunch: function () {
    // 微信小程序启动之后 触发
  }
})

整个微信小程序只有一个 App 实例,是全部页面共享的,更多的事件回调参考文档 注册程序 App 。

接下来我们简单看看微信小程序的一个页面是怎么写的。

你可以观察到 pages/logs/logs 下其实是包括了4种文件的,微信客户端会先根据 logs.json 配置生成一个界面,顶部的颜色和文字你都可以在这个 json 文件里边定义好。紧接着客户端就会装载这个页面的 WXML 结构和 WXSS 样式。最后客户端会装载 logs.js,你可以看到 logs.js 的大体内容就是:

Page({
  data: { // 参与页面渲染的数据
    logs: []
  },
  onLoad: function () {
    // 页面渲染后 执行
  }
})

Page 是一个页面构造器,这个构造器就生成了一个页面。在生成页面的时候,微信小程序框架会把 data 数据和 index.wxml 一起渲染出最终的结构,于是就得到了你看到的微信小程序的样子。

在渲染完界面之后,页面实例就会收到一个 onLoad 的回调,你可以在这个回调处理你的逻辑。

有关于 Page 构造器更多详细的文档参考 注册页面 Page 。

渲染层和逻辑层

首先,我们来简单了解下微信小程序的运行环境。微信小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。

微信小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个微信小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发,微信小程序的通信模型下图所示。

有关渲染层和逻辑层的详细文档参考 微信小程序框架 。

JS 逻辑交互

一个服务仅仅只有界面展示是不够的,还需要和用户做交互:响应用户的点击、获取用户的位置等等。在微信小程序里边,我们就通过编写 JS 脚本文件来处理用户的操作。

<view>{{ msg }}</view>
<button bindtap="clickMe">点击我</button>

点击 button 按钮的时候,我们希望把界面上 msg 显示成 "Hello World",于是我们在 button 上声明一个属性: bindtap ,在 JS 文件里边声明了 clickMe 方法来响应这次点击操作:

Page({
  clickMe: function() {
    this.setData({ msg: "Hello World" })
  }
})

响应用户的操作就是这么简单,更详细的事件可以参考文档 WXML – 事件 。

此外你还可以在 JS 中调用微信小程序提供的丰富的 API,利用这些 API 可以很方便的调起微信提供的能力,例如获取用户信息、本地存储、微信支付等。在前边的 QuickStart 例子中,在 pages/index/index.js 就调用了 wx.getUserInfo 获取微信用户的头像和昵称,最后通过 setData 把获取到的信息显示到界面上。更多 API 可以参考文档 微信小程序的API 。

通过这个章节,你了解了微信小程序涉及到的文件类型以及对应的角色,在下个章节中,我们把这一章所涉及到的文件通过 “微信小程序的框架” 给 “串” 起来,让他们都工作起来。

WXSS 样式

WXSS 具有 CSS 大部分的特性,微信小程序在 WXSS 也做了一些扩充和修改。

  1. 新增了尺寸单位。在写 CSS 样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。WXSS 在底层支持新的尺寸单位 rpx ,开发者可以免去换算的烦恼,只要交给微信小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。

  2. 提供了全局的样式和局部样式。和前边 app.json, page.json 的概念相同,你可以写一个 app.wxss 作为全局样式,会作用于当前微信小程序的所有页面,局部页面样式 page.wxss 仅对当前页面生效。

  3. 此外 WXSS 仅支持部分 CSS 选择器

更详细的文档可以参考 WXSS 。

WXML 模板

从事过网页编程的人知道,网页编程采用的是 HTML + CSS + JS 这样的组合,其中 HTML 是用来描述当前这个页面的结构,CSS 用来描述页面的样子,JS 通常是用来处理这个页面和用户的交互。

同样道理,在微信小程序中也有同样的角色,其中 WXML 充当的就是类似 HTML 的角色。打开 pages/index/index.wxml,你会看到以下的内容:

<view class="container">
  <view class="userinfo">
    <button wx:if="{{!hasUserInfo && canIUse}}"> 获取头像昵称 </button>
    <block wx:else>
      <image src="{{userInfo.avatarUrl}}" background-size="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
</view>

HTML 非常相似,WXML 由标签、属性等等构成。但是也有很多不一样的地方,我们来一一阐述一下:

  1. 标签名字有点不一样

    往往写 HTML 的时候,经常会用到的标签是 div, p, span,开发者在写一个页面的时候可以根据这些基础的标签组合出不一样的组件,例如日历、弹窗等等。换个思路,既然大家都需要这些组件,为什么我们不能把这些常用的组件包装起来,大大提高我们的开发效率。

    从上边的例子可以看到,微信小程序的 WXML 用的标签是 view, button, text 等等,这些标签就是微信小程序给开发者包装好的基本能力,我们还提供了地图、视频、音频等等组件能力。

    更多详细的组件讲述参考下个章节 微信小程序的能力

  2. 多了一些 wx:if 这样的属性以及 {{ }} 这样的表达式

    在网页的一般开发流程中,我们通常会通过 JS 操作 DOM (对应 HTML 的描述产生的树),以引起界面的一些变化响应用户的行为。例如,用户点击某个按钮的时候,JS 会记录一些状态到 JS 变量里边,同时通过 DOM API 操控 DOM 的属性或者行为,进而引起界面一些变化。当项目越来越大的时候,你的代码会充斥着非常多的界面交互逻辑和程序的各种状态变量,显然这不是一个很好的开发模式,因此就有了 MVVM 的开发模式(例如 React, Vue),提倡把渲染和逻辑分离。简单来说就是不要再让 JS 直接操控 DOMJS 只需要管理状态即可,然后再通过一种模板语法来描述状态和界面结构的关系即可。

    微信小程序的框架也是用到了这个思路,如果你需要把一个 Hello World 的字符串显示在界面上。

    WXML 是这么写 :

    <text>{{msg}}</text>
    

    JS 只需要管理状态即可:

    this.setData({ msg: "Hello World" })
    

    通过 {{ }} 的语法把一个变量绑定到界面上,我们称为数据绑定。仅仅通过数据绑定还不够完整的描述状态和界面的关系,还需要 if/else, for等控制能力,在微信小程序里边,这些控制能力都用 wx: 开头的属性来表达。

更详细的文档可以参考 WXML

JSON 配置

JSON 是一种数据格式,并不是编程语言,在微信小程序中,JSON 扮演着静态配置的角色。

我们可以看到在项目的根目录有一个 app.jsonproject.config.json,此外在 pages/logs 目录下还有一个 logs.json,我们依次来说明一下它们的用途。

微信小程序配置 app.json

app.json 是当前微信小程序的全局配置,包括了微信小程序的所有页面路径、界面表现、网络超时时间、底部标签栏等。QuickStart 项目里边的 app.json 配置内容如下:

{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black"
  }
}

我们简单说一下这个配置各个项的含义:

  1. pages字段 —— 用于描述当前微信小程序所有页面路径,这是为了让微信客户端知道当前你的微信小程序页面定义在哪个目录。
  2. window字段 —— 定义微信小程序所有页面的顶部背景颜色、文字颜色定义等。

其他配置项细节可以参考文档 微信小程序的配置 app.json。

工具配置 project.config.json

通常大家在使用一个工具的时候,都会针对各自喜好做一些个性化配置,例如界面颜色、编译配置等等,当你换了另外一台电脑重新安装工具的时候,你还要重新配置。

考虑到这点,微信小程序开发者工具在每个项目的根目录都会生成一个 project.config.json,你在工具上做的任何配置都会写入到这个文件。当你重新安装工具或者换电脑工作时,只要载入同一个项目的代码包,开发者工具就会自动帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等等一系列选项。

其他配置项细节可以参考文档 开发者工具的配置。

页面配置 page.json

这里的 page.json 其实用来表示 pages/logs 目录下的 logs.json 这类和微信小程序页面相关的配置。

如果你整个微信小程序的风格是蓝色调,那么你可以在 app.json 里边声明顶部颜色是蓝色即可。实际情况可能不是这样,可能你微信小程序里边的每个页面都有不一样的色调来区分不同功能模块,因此我们提供了 page.json,让开发者可以独立定义每个页面的一些属性,例如刚刚说的顶部颜色、是否允许下拉刷新等等。

其他配置项细节可以参考文档 页面配置。

JSON 语法

这里说一下微信小程序里 JSON 配置的一些注意事项。

JSON 文件都是被包裹在一个大括号 {} 中,通过 key-value 的方式来表达数据。JSON 的 Key 必须包裹在双引号中,在实践中,编写 JSON 的时候,忘了给 Key 值加双引号或者是把双引号写成单引号是常见错误。

JSON 的值只能是以下几种数据格式,其他任何格式都会触发报错,例如 JavaScript 中的 undefined。

  1. 数字,包含浮点数和整数
  2. 字符串,需要包裹在双引号中
  3. 布尔值,true 或者 false
  4. 数组,需要包裹在方括号中 []
  5. 对象,需要包裹在大括号中 {}
  6. Null

还需要注意的是 JSON 文件中无法使用注释,试图添加注释将会引发报错。