一、小程序开发账号
- 在小程序管理平台,用邮箱注册一个账号appID,一个邮箱只能申请一个
- appID相当于小程序的身份证,一个appID只能对应一个线上小程序
二、小程序的注册
- app.js
1.1 每个小程序都需要在app.js中通过小程序构造器App()注册小程序示例,绑定生命周期函数以及错误监听函数,定义全局的变量或方法
1.2 小程序提供getApp()函数来获取小程序实例,使用这个实例可以在每个页面中调用app.js中的全局变量或方法
1.3 小程序的生命周期如下
// app.js
App({
onLaunch (options) {
// 小程序初始化
},
onShow (options) {
// 小程序初始化完成之后或者小程序从后台改为前台运行,监听小程序的显示
},
onHide () {
// 小程序从前台改为后台运行,监听小程序的隐藏
},
onError (msg) {
// 监听小程序的错误
console.log(msg)
},
globalData: 'I am global data'
})
- app.json
2.1 pages数组,所有的页面都要在这个数组中进行注册,数组中的第一个页面表示小程序的初始页面,而且pages数组中页面的数量与真正的页面数量、路径要一一对应,新增或者减少页面都要对app.json的pages数组进行修改
2.2 window对象,设置小程序窗口的默认表现形式,比如设置标题栏背景、文字颜色等样式
2.3 tabBar对象,设置小程序底部的导航,数量最少为2个,最多为5个,按照导航的顺序排列
三、代码的组成
主体(app):app.js(小程序逻辑)、app.json(小程序公共配置)、app.wxss(小程序公共样式)
页面(pages):每一个都由以下四个文件组成
- index.wxss 页面的样式,定义在app.wxss的全局样式作用于所有页面,而在pages中定义的样式只作用于对应的页面,会覆盖全局中相同的样式。小程序中一般用rpx作为像素单位,可以根据不同手机的页面进行自适应,微信官方建议以iphone6为标准:iPhone6: 1rpx=0.5px,iPhone5: 1rpx=0.42px,iPhone6Plus: 1rpx=0.552px
- index.json 页面的配置文件,包括组件的引用和设置window对象,会覆盖app.json中相同的window配置
- index.js 页面的脚本,通过页面构造器Page()注册页面,可以指定页面的初始数据、生命周期、事件处理函数等,所有操作数据的方法都在这个文件中执行
- index.wxml 页面模板,使用微信自定义的组件,也可以使用其他UI框架的组件
pages页面的生命周期如下
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// 监听页面创建
},
onShow: function() {
// 监听页面在前台的显示,每次打开页面都会调用一次
},
onReady: function() {
// 监听页面首次渲染完毕
},
onHide: function() {
// 监听页面的隐藏,比如从前台切换到后台运行
},
onUnload: function() {
// 监听页面的销毁,通过路由跳出页面后会触发这个函数
},
onPullDownRefresh: function() {
// 监听页面的下拉刷新
},
onReachBottom: function() {
// 监听页面的触底
},
onPageScroll: function() {
// 监听页面的滚动
}
})
四、路由
- wx.navigateTo 跳转新页面,跳转页面后保留前一页面(onHide)
- wx.redirectTo 页面重定向,跳转页面后不保留前一页面(onUnload)
- wx.navigateBack 页面返回,跳转页面后不保留前一页面(onUnload)
- wx.switchTab 当跳转的页面是一个tab页时,只能通过这个方式跳转
- wx.reLaunch 重启动页面
五、页面栈
- 小程序提供了getCurrentPages()方法来获取页面栈,返回一个数组,第一个元素为首页,最后一个元素为当前页面。每个元素对应一个页面对象,通过这个页面对象可以调用对应页面中的变量和方法,可以轻松地实现页面之间的数据通信
let pages = getCurrentPages()
//当前页面
let currPage = pages[pages.length - 1]
//上一个页面
let prevPage = pages[pages.length - 2]
//调用上一个页面对象的setData()方法,把数据存入上一个页面
prevPage.setData({
data:data
})
六、视图层
- 标签:小程序一般使用view、button、text等而不使用div、span、p等
- 数据绑定:在js文件中的data中定义后,在布局页面中通过{{ }}的形式进行绑定
- 条件逻辑:wx:if=“{{ }}” wx:elif=“{{ }}” wx:else=“{{ }}”
- 列表渲染:wx:for=“{{ }}” wx:key=“”,默认当前项变量名为item,当前下标为index,还可以通过wx:for-item=“”、wx:for-index=""来自定义变量名
- 事件绑定:通过bind(默认冒泡)、catch(阻止冒泡)绑定,常用事件:tap(点击事件)、longtap(长按事件)、touchstart(触摸开始)、touchend(触摸结束)、touchcancel(触摸取消)、touchmove(触摸后移动)、touchforcechange(重按,仅对支持3DTouch的iPhone)
- 事件绑定时传值:通过‘ data- ’传递,在相应的事件函数中,通过事件对象‘ e.currentTarget.dataset ’获取
七、数据通信
- 全局变量:app.globalData
- 本地缓存:wx.setStorageSync/wx.getStorageSync(同步)、wx.setStorage/wx.getStorage(异步),最大为10MB
- 跳转页面时通过url传递
八、运行机制
- 冷启动:是指用户首次打开小程序或者小程序被微信主动销毁后再次打开
- 热启动:是指用户之前有打开过小程序,然后在一定时间内再次打开小程序,无需重新启动
九、更新机制:
- 若小程序是冷启动,则会自动下载最新版本的代码包,也就是会自动运行最新版本
- 若小程序是热启动,则无法检测最新版本,需要通过getUpdateManager接口检测版本更新,如下
App({
onLaunch: function () {
// 检查更新
this.autoUpdate()
},
autoUpdate: function(){
let _this = this
// 获取小程序更新机制的兼容,由于更新的功能基础库要1.9.90以上版本才支持,所以此处要做低版本的兼容处理
if(wx.canIUse('getUpdateManager')){
// wx.getUpdateManager接口,可以获知是否有新版本的小程序、新版本是否下载好以及应用新版本的能力,会返回一个UpdateManager实例
const updateManager = wx.getUpdateManager()
// 检查小程序是否有新版本发布,onCheckForUpdate:当小程序向后台请求完新版本信息,会通知这个版本告知检查结果
updateManager.onCheckForUpdate(function(res){
// 请求完新版本信息的回调
if(res.hasUpdate){
// 检测到新版本,需要更新,给出提示
wx.showModal({
title: '更新提示',
content: '检测到新版本,是否下载新版本并重启小程序',
success: function(res){
if(res.confirm){
// 用户确定更新小程序,小程序下载和更新静默进行
_this.downLoadAndUpdate(updateManager)
}else if(res.cancel){
// 若用户点击了取消按钮,二次弹窗,强制更新,如果用户选择取消后不需要进行任何操作,则以下内容可忽略
wx.showModal({
title: '提示',
content: '本次版本更新涉及到新功能的添加,旧版本将无法正常使用',
showCancel: false, // 隐藏取消按钮
confirmText: '确认更新', // 只保留更新按钮
success: function(res){
if(res.confirm){
// 下载新版本,重启应用
_this.downLoadAndUpdate(updateManager)
}
}
})
}
}
})
}
})
} else {
// 在最新版本客户端上体验小程序
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试',
})
}
},
// 下载小程序最新版本并重启
downLoadAndUpdate: function(updateManager){
wx.showLoading()
// 静默下载更新小程序最新版本,onUpdateReady:新版本下载完成的回调
updateManager.onUpdateReady(function(){
wx.hideLoading()
// applyUpdate:强制当前小程序应用上新版本并重启
updateManager.applyUpdate()
})
// onUpdateFailed:新版本下载失败的回调
updateManager.onUpdateFailed(function(){
// 下载新版本失败
wx.showModal({
title: '已有新版本',
content: '新版本已经上线了,请删除当前小程序,重新搜索打开',
})
})
}
})
十、用户授权登录
从上图可以看出,小程序的登录步骤如下
- 前端使用wx.login()从微信服务器获取code
- 前端将code发送给后端,后端通过appID、appSecret和code向微信服务器换取用户的openId(当前用户的唯一标识)和session_key(密钥)
- 前端通过session_key可以将从微信服务器拿到的encryptedData解密,获取到openId、unionId(同一用户对于同一微信公众号下的不同应用,unionId是相同的)
- 后端自定义登录状态返回前端
- 前端将获取到的登录状态通过本地缓存保存起来
- 当前端调用后端接口时,将登录状态发送给后端,让后端知道当前的操作用户
十一、小程序云开发
简单的来说,小程序云开发是一款 Serverless 服务,弱化后端和运维概念,无需搭建服务器,核心功能包括云存储、云数据库、云函数,并且将这些能力封装成特定的api,用 wx.cloud 进行调用。
- 云函数:在云端运行的代码
- 云数据库:既可在小程序前端操作,也能在云函数中读写的 JSON 数据库
- 云存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
十二、云数据库基本操作
首先,引用数据库,初始化数据库对象
const db = wx.cloud.database()
- 插入操作:
// collection('user') 获取到数据库中名为 user 的集合
// add 插入操作
db.collection('user').add({
// 要插入的数据
data: {
name: 'Tom',
age: 18
}
}).then(res => {
// 插入数据成功
}).catch(err => {
// 插入数据失败
})
注意:插入数据库的数据为额外有两个id:_id(数据的主键id),_openid(这条数据的创建者的openid);
直接从云数据库控制台插入的数据是没有openid的
- 查询操作:
// where 查询操作
db.collection('user').where({
// 查询条件
name: 'Tom'
})
.get()
.then(res => {
// 查询数据成功
}).catch(err => {
// 查询数据失败
})
- 更新操作:
// update 更新操作
// primary key 要更新的那条数据的主键id
db.collection('user').doc('primary key')
.update({
// 想要更新后的数据
data: {
age: 20
}
}).then(res => {
// 更新数据成功
}).catch(err => {
// 更新数据失败
})
- 删除操作:
// remove 删除操作
// primary key 要删除的那条数据的主键id
db.collection('user').doc('primary key')
.remove()
.then(res => {
// 删除数据成功
}).catch(err => {
// 删除数据失败
})
注意:此方法只适用于一次删除一条数据,若想实现批量删除数据,则要使用云函数,如下
- 使用云函数批量删除数据:
5.1 新建云函数(batchDelete),在云函数的入口文件中
// 云函数入口文件
const cloud = require('wx-server-sdk')
// 初始化云数据库
const db = wx.cloud.database()
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
try {
// 找到集合user中name为Tom的所有数据并删除
return await db.collection('user').where({
name: 'Tom'
}).remove()
} catch (err) {
console.error(err)
}
}
注意:云函数创建或有任何修改后,都需要手动部署到云端后才可生效
5.2 在页面的js中调用这个云函数
// callFunction 调用云函数
wx.cloud.callFunction({
// 云函数名称
name: 'batchDelete',
data: {
param: '123'
}
}).then(res => {
console.log(res)
}).catch(err => {
console.error(err)
})