简介
- 到目前为止,很多平台都有自己的小程序。最早推出小程序的是微信团队。本文以微信小程序为代表。
小程序发展历程
- 2016年1月9日,小程序立项
- 2016年9月21日,开始内测
- 2017年1月9日,正式上线
小程序和APP
- 相比手机应用小程序更为轻量级一些,无需单独下载。
- 小程序运行在宿主APP中。依靠速度APP的巨大流量,推送营销的成本较为低一些。
- 与手机APP单独语言的开发。使用前端技术开发的小程序,更为友好一些,不需要单独安卓或ios开发工程师。
小程序和普通网页开发的区别
小程序开发的主要语言是js。小程序开发和普通的网页开发有很大的相似性。技术迁移的成本并不高嗯,但还是有一些区别。
- 网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。
- 小程序中不能使用 HTML。
- DOM 和 BOM 在小程序中不可用,基于 DOM 和 BOM 的 JS 库也不能用。
- 小程序的运行环境与网页开发不同
- 网页开发的运行环境是浏览器
- 小程序的运行环境是操作系统(Android 和 iOS)上的客户端
- 小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
小程序的运行环境
渲染层和逻辑层
-
小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
-
小程序的渲染层和逻辑层分别由2个线程管理
- 渲染层的界面使用了WebView 进行渲染
- 逻辑层采用 JsCore 线程运行 JS 脚本
-
一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由客户端做中转,逻辑层发送网络请求也经由 Native 转发。
小程序基础
注册账号
需要拥有一个小程序帐号,通过这个帐号你就可以管理你的小程序。
进入小程序注册页 根据指引填写信息和提交相应的资料,就可以拥有自己的小程序帐号。
在这个小程序管理平台,你可以管理你的小程序的权限,查看数据报表,发布小程序等操作。
注册过微信公众号的邮箱,不能再注册微信小程序账号。
登录 小程序后台 ,可以在菜单 “设置”-“基本设置” -“帐号信息”看到小程序的 AppID 了 。
小程序的 AppID 相当于小程序平台的一个身份证,后续你会在很多地方要用到 AppID (注意这里要区别于服务号或订阅号的 AppID)。
安装开发工具
在 开发者工具下载页面 ,根据自己的操作系统下载对应的安装包进行安装。
打开小程序开发者工具,用微信扫码登录开发者工具。
创建小程序
- 填写项目名称
- 选择代码存放的硬盘路径
- 填入小程序的 AppID
- 勾选 "不使用云服务"
- 选择一个模板
- 点击新建
编译预览
点击工具上的编译按钮,可以在工具的左侧模拟器界面看到这个小程序的表现,也可以点击预览按钮,通过微信的扫一扫在手机上体验小程序。
目录结构
小程序包含一个描述整体程序的 app 和多个描述各自页面的 page。
全局文件
上述三个文件,在项目的根目录下,文件位置和文件名(包括后缀名)是固定的(都不能改)。
- app.js 是小程序启动后,加载的入口文件
- app.json 是整个小程序项目的配置文件
- app.wxss 是整个小程序项目的全局样式文件
页面文件
在小程序中,每个具体的页面都由四个文件组成。页面的四个文件必须具有相同的路径与文件名。
- name.js 当前页面的入口文件
- name.json 当前页面的配置文件
- name.wxml 当前页面的内容(相当于浏览器端的 HTML)
- name.wxss 当前页面的样式文件,你可以在此写 CSS 代码
快速生成页面文件
如果要新建页面文件,只需要在 app.json 中的 pages 字段中指定,然后保存 app.json。这样页面文件就会自动创建出来。
小程序配置
全局配置
小程序根目录下的 app.json
文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
完整配置项说明请参考小程序全局配置
页面配置
每一个小程序页面也可以使用同名 .json
文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json
的 window
中相同的配置项。
完整配置项说明请参考小程序页面配置
生命周期
小程序的生命周期是指小程序生命的不同阶段。这里的周期主要指两个循环状态: 前台到后台; 初始化到销毁。
在小程序生命的不同阶段, 都会自动触发函数,可以在生命周期函数中, 添加相应业务逻辑。小程序的生命周期可以分为两类:
- 小程序的生命周期:描述小程序整个项目的不同阶段
- 页面生命周期:描述页面的不同阶段
小程序的生命周期
每个小程序都需要在 app.js
中调用 App
方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。
详细的参数含义和使用请参考 App 参考文档 。
// app.js
App({
onLaunch (options) {
// 监听小程序初始化。
},
onShow (options) {
// 监听小程序启动或切前台。
},
onHide () {
// 监听小程序切后台。
},
onError (msg) {
// 错误监听函数。
console.log(msg)
},
globalData: 'I am global data'
})
注意:
- onLaunch: 全局只调用一次(逻辑只执行一次)
- onShow: 应用初始化完成; 从后台切换到前台
- onHide: 从前台切换到后台(小程序应用转到别的应用)
整个小程序只有一个 App 实例,是全部页面共享的。可以通过 getApp
方法获取到全局唯一的 App 实例,获取 App 上的数据或调用开发者注册在 App
上的函数。
// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data
页面生命周期
下图说明了页面 Page
实例的生命周期。
对于小程序中的每个页面,都需要在页面对应的 js
文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。
简单的页面可以使用 Page()
进行构造。
示例:
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// 页面创建时执行
},
onShow: function() {
// 页面出现在前台时执行
},
onReady: function() {
// 页面首次渲染完毕时执行
},
onHide: function() {
// 页面从前台变为后台时执行
},
onUnload: function() {
// 页面销毁时执行
},
onPullDownRefresh: function() {
// 触发下拉刷新时执行
},
onReachBottom: function() {
// 页面触底时执行
},
onShareAppMessage: function () {
// 页面被用户分享时执行
},
onPageScroll: function() {
// 页面滚动时执行
},
onResize: function() {
// 页面尺寸变化时执行
},
onTabItemTap(item) {
// tab 点击时执行
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
},
// 事件响应函数
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
},
// 自由数据
customData: {
hi: 'MINA'
}
})
详细的参数含义和使用请参考 Page 参考文档 。
小程序API
小程序开发框架提供丰富的原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。详细介绍请参考 API 文档。
通常,在小程序 API 有以下几种类型:
事件监听 API
约定,以 on
开头的 API 用来监听某个事件是否触发,如:wx.onSocketOpen,wx.onCompassChange 等。
这类 API 接受一个回调函数作为参数,当事件触发时会调用这个回调函数,并将相关数据以参数形式传入。
wx.onCompassChange(function (res) {
console.log(res.direction)
})
同步 API
我们约定,以 Sync
结尾的 API 都是同步 API, 如 wx.setStorageSync,wx.getSystemInfoSync 等。此外,也有一些其他的同步 API,如 wx.createWorker,wx.getBackgroundAudioManager 等,详情参见 API 文档中的说明。
同步 API 的执行结果可以通过函数返回值直接获取,如果执行出错会抛出异常。
try {
wx.setStorageSync('key', 'value')
} catch (e) {
console.error(e)
}
异步 API
大多数 API 都是异步 API,如 wx.request,wx.login 等。这类 API 接口通常都接受一个 Object
类型的参数,这个参数都支持按需指定以下字段来接收接口调用结果:
Object 参数说明
回调函数的参数
success
,fail
,complete
函数调用时会传入一个 Object
类型参数,包含以下字段:
异步 API 的执行结果需要通过 Object
类型的参数中传入的对应回调函数获取。部分异步 API 也会有返回值,可以用来实现更丰富的功能,如 wx.request,wx.connectSocket 等。
wx.login({
success(res) {
console.log(res.code)
}
})
异步 API 返回 Promise
异步 API 支持 callback & promise 两种调用方式。当接口参数 Object 对象中不包含 success/fail/complete 时将默认返回 promise,否则仍按回调方式执行,无返回值。
注意事项
- 部分接口如
downloadFile
,request
,uploadFile
,connectSocket
,createCamera
(小游戏)本身就有返回值, 它们的 promisify 需要开发者自行封装。 - 当没有回调参数时,异步接口返回 promise。此时若函数调用失败进入 fail 逻辑, 会报错提示
Uncaught (in promise)
,开发者可通过 catch 来进行捕获。 - wx.onUnhandledRejection 可以监听未处理的 Promise 拒绝事件。
// callback 形式调用
wx.chooseImage({
success(res) {
console.log('res:', res)
}
})
// promise 形式调用
wx.chooseImage().then(res => console.log('res: ', res))
实践
1.获取位置信息
- 获取地理位置接口
wx.getLocation({
type: 'wgs84',// wgs84 返回 gps 坐标
success(res) {
console.log(res);
}
})
- 在 app.json 里声明 permission 字段
"permission": {
"scope.userLocation": {
"desc": "服务需要位置信息"
}
},
- 获取结果
{
accuracy: 65
errMsg: "getLocation:ok"
horizontalAccuracy: 65
latitude: 30.2084
longitude: 120.21201
speed: -1
verticalAccuracy: 65
}
2.通过 wx.request 调用接口
wx.request({
url: 'example.php', //仅为示例,并非真实的接口地址
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success (res) {
console.log(res.data)
}
})
请求报错:发送接口请求时,请求域名必须是https协议,而且必须绑定到小程序管理平台。
本地解决方案:
不检查域名是否合法
线上解决方案:
把报错域名,添加到微信公众平台(小程序账号)
路径:开发 -> 开发管理 -> 开发设置 -> 服务器域名
3.第三方UI组件
这里使用WeUI组件。WeUI 是微信团队推出的,针对小程序开发的 UI 组件库。
-
下载文件:
-
将下图样式文件复制到项目中
- 引入样式文件
@import './weui.wxss';
/**app.wxss**/
- 在开发工具中查看ui组件源码
4.WXML模板
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。
参考资料:developers.weixin.qq.com/miniprogram…
示例:
<!-- 编写模板 -->
<template name="page_footer">
<view class="weui-footer">
已到底部
</view>
</template>
<!-- 使用模板 -->
<import src="/templates/footer"/>
<template is="page_footer"></template>
5.体验照相
效果:
代码:
<view>
<camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 500rpx;"></camera>
<button type="primary" bindtap="takePhoto">拍照</button>
<view>预览</view>
<image mode="widthFix" style="width: 100%;" src="{{src}}"></image>
</view>
Page({
/**
* 页面的初始数据
*/
data: {
},
takePhoto() {
const ctx = wx.createCameraContext()
ctx.takePhoto({
quality: 'high',
success: (res) => {
this.setData({
src: res.tempImagePath
})
}
})
}
})
6.小程序发布
小程序从开发完到上线一般要经过 预览-> 上传代码 -> 提交审核 -> 发布等步骤。
- 扫码预览
- 上传代码
上传成功之后,登录小程序管理后台 - 版本管理 - 开发版本 就可以找到刚提交上传的版本了。
可以将这个版本设置 体验版 或者是 提交审核。
-
提交审核
-
小程序的发布是需要经过审核的。
-
登录 小程序管理后台 - 版本管理 - 开发版本 找到提交上传的版本。
-
-
发布
审核通过之后,会收到小程序通过审核的通知,此时登录 小程序管理后台 - 开发管理 - 审核版本中可以看到通过审核的版本。
点击发布后,即可发布小程序。