提前说下:
写这两篇笔记,纯看文档,没有实践、测试代码,是否正确,错误的地方可能会很多!只是帮我梳理了下小程序文档。
本笔记,只记录某些重点,或不太清楚的,一般的不做笔记
1.小程序配置
全局配置(app.json)
window - 用于设置小程序的状态栏、导航条、标题、窗口背景色等
enablePullDownRefresh - 是否开启全局的下拉刷新(默认:false)
/*
对应 '页面事件处理函数' -> onPullDownRefresh
框架 -> 框架接口 -> 页面 -> Page
onPullDownRefresh() - 监听用户下拉刷新事件
1.需要在 app.json 的 window 选项(全局配置)或 '页面配置',开启 'enablePullDownRefresh'
2.监听到事件触发,我们就可以通过 'wx.request' 请求数据(我们也可以通过 'wx.startPullDownRefresh' 来主动触发下拉刷新,跟上面配置的 enablePullDownRefresh 后,与用户手动下拉刷新效果一致)
// 主动通过 API 来下拉刷新
wx.startPullDownRefresh({
success(e){
wx.request({
....
})
}
})
3.数据请求完毕后,我们可以调用 'wx.stopPullDownRefresh',停止当前页面的下拉刷新
Page({
onPullDownRefresh(){
// 结束下拉刷新
wx.stopPullDownRefresh()
}
})
*/
onReachBottomDistance - 页面下拉触底事件,触发时距页面底部距离,单位为 px(默认:50)
/*
对应 '页面事件处理函数' -> onReachBottom
框架 -> 框架接口 -> 页面 -> Page
onReachBottom() - 监听用户上拉触底事件
1.需要在 app.json 的 window 选项(全局配置)或 '页面配置',配置触底距离 'onReachBottomDistance'
2.在触发距离内滑动期间,事件只会触发一次
*/
pageOrientation - 屏幕旋转设置,支持:auto | portrait | landscape(默认:portrait)
portrait - 头像、肖像(竖向打印格式)
landscape - 风景、景色(横向打印格式)
tabBar - tabBar 设置
custom - 是否是自定义 tabBar(默认:false),记得看之前的笔记(自定义 tabBar 会接管 tabBar,但是为了兼容旧版,也需要完整的其他 tabBar 参数的配置)
requiredBackgroundModes - 需要在后台使用的能力,如 '音乐播放'。
类型为数组,目前只支持:audio - 后台音乐播放
"requiredBackgroundModes": ["audio"]
注意:
开发版和体验版,直接生效
正式版,需要微信官方审核
navigateToMiniProgramAppIdList - 需要跳转的小程序列表
如果要跳转到其他小程序,这里配置需要跳转的小程序 appId 列表,最多 10 个
usingComponents - 此处声明的自定义组件为全局组件,在小程序的页面或自定义组件中,我们可以直接使用,而不用再次声明
permission - 小程序接口权限相关设置
授权类型为:scope.userLocation - 地理位置,提示的文字
"permission": {
"scope.userLocation": {
"desc": "小程序获取权限时展示的接口用途说明,最长 30 个字符"
}
}
页面配置(page/xxx.json)
enablePullDownRefresh - 对应 window 的 enablePullDownRefresh
onReachBottomDistance - 对应 window 的 onReachBottomDistance
pageOrientation - 对应 window 的 pageOrientation
disableScroll - 是否禁用页面滚动,设置为 true,则页面整体不能上下滚动(默认:false)
disableSwipeBack - 是否禁止页面 '右滑手势' 返回(默认:false)
usingComponents - 页面使用的 '自定义组件' 列表
sitemap 配置(sitemap.json)
小程序内搜索,可以爬取小程序页面而建立索引,让用户直接在微信中,可以搜索到小程序的页面。
具体看文档
2.App() 方法
注册小程序,入口方法
App() 必须在 app.js 入口文件调用,只能调用 '一次'
参数对象:
onLaunch - 生命周期回调,监听小程序初始化
1.全局只触发一次
2.参数也可以通过 wx.getLaunchOptionsSync 获取
onLaunch(options){
// options 同 wx.getLaunchOptionsSync() 的参数一致
// 不使用 options,也可以使用 wx.getLaunchOptionsSync() 来获取,得到的结果和 options 一致
}
2.参数与 'wx.getLaunchOptionsSync' 一致
path - 启动小程序的路径
scene - 启动小程序的场景值(查看:'指南 -> 小程序框架 -> 场景值' 或者 '当前文档页下方也有',2 者内容是一致的)
query - 启动小程序的 query 参数
shareTicket - 转发设置的 withShareTicket: true,可以获取到 shareTicket
referrerInfo - 来源信息。从另一个小程序、公众号或 App 进入小程序时返回。否则返回 '{}'
appId - 来源小程序、公众号或 App 的 appid
extraData - 来源小程序传过来的数据,scene = 1037或1038 时支持
注意:
部分版本在无 referrerInfo 时,会返回 undefined,建议使用:
options.referrerInfo && options.referrerInfo.appId
来进行判断
onShow - 生命周期回调,监听小程序启动或 '从后台进入前台显示时触发'
1.也可以使用 wx.onAppShow() 绑定监听
wx.onAppShow(function(res){
})
2.参数与 wx.onAppShow() 一致,上面的 res 参数如下:
path - 小程序切前台的路径
scene - 小程序切前台的场景值(查看:'指南 -> 小程序框架 -> 场景值' 或者 '当前文档页下方也有',2 者内容是一致的)
query - 小程序切前台的 query 参数
shareTicket - 转发设置的 withShareTicket: true,可以获取到 shareTicket
referrerInfo - 和上面的 onLaunch 一致
appId -
extraData -
/*
发现 onShow 和 onLaunch 的参数一致
*/
onHide - 生命周期回调,监听小程序切后台
1.也可以使用 wx.onAppHide() 绑定监听
2.无参数
onError - 监听错误
1.也可以使用 wx.onError() 绑定监听
2.参数
error - 错误信息,包含堆栈
onPageNotFound - 监听页面不存在
1.也可以使用 wx.onPageNotFound() 绑定监听
2.参数与 wx.onPageNotFound() 一致
path - 不存在页面的路径
query - 打开不存在页面的 query 参数
isEntryPage - 是否本次启动的首个页面(例如:从分享入口进来,首个页面是开发者配置的分享页面)
3.回调中处理
1>我们可以在回调中进行页面重定向,但必须 '同步' 处理,异步处理无效(例如:setTimeout)
2>如果没有声明 onPageNotFound 监听,当跳转页面不存在时,将推入 '微信客户端原生的页面不存在的提示页面'
3>如果回调中,重定向到另一个页面,而该页面扔不存在,将推入 '微信客户端原生的页面不存在的提示页面',不进行第二次回调。
以及其他的自定义的全局属性和方法,例如:
userName - 用户名
age - 年龄
getAvatar() - 获取头像方法
...
3.getApp() 方法
获取到小程序全局唯一的 App 实例
参数:
allowDefault - 在 App 未定义时,返回默认实现。当 App 被调用时,默认实现中定义的属性会被覆盖合并到 App 中(主要是作用域 '独立分包',加载时,可能还没有 App 实现)
注意:
1>不要在定义在 App() 内的函数中(或调用 App 之前,不理解),调用 getApp(),使用 this 就可以获取 app 实例
2>通过 getApp() 获取实例后,不要私自调用生命周期函数
4.Page() 方法
注册一个页面。指定页面的初始数据、生命周期回调、事件处理函数等
data - 页面的初始数据
生命周期回调
onLoad - 页面加载时触发
1.一个页面只会调用一次
2.可以在 onLoad 回调中,获取打开当前页面路径中的参数
query - 打开当前页面的参数
onShow - 页面 '显示' | '切入前台' 时触发
onReady - 页面初次渲染完成触发。
1.一个页面只会调用一次
2.代表页面已经准备妥当,可以和视图层进行交互。对界面内容进行设置的 API,如:wx.setNavigationBarTitle,只能在 onReady 之后进行
onHide - 页面 '隐藏' | '切入后台' 时触发
1.如 wx.navigateTo 或 底部 tabBar 切换到其他页面,或小程序切入后台
onUnload - 页面卸载时触发
1.如 wx.redirectTo 或 wx.navigateBack 到其他页面
页面事件处理函数
onPullDownRefresh - 参考上面的 window 配置
onReachBottom - 参考上面的 window 配置
onPageScroll - 监听页面滑动事件
1.参数对象
scrollTop - 页面在垂直方向已滚动的距离(单位 px)
2.注意:
1>只在需要的时候才在 Page() 中定义该方法,不要定义空方法,减少不必要的事件派发
2>避免在方法中,过于频繁的执行 setData(),尤其是每次传输大量数据,会影响通信耗时,造成卡顿(优化提到过 '逻辑层和渲染层通讯' 原理)
onShareAppMessage - 监听用户转发,并自定义转发内容
1.查看 '之前的转发' 笔记
2.只有定义了该事件回调,右上角才会显示 '转发' 按钮
onResize - 小程序屏幕旋转时触发
onTabItemTap - 点击 tab 时触发
1.参数对象
index - 被点击 tabItem 的索引,从 0 开始
pagePath - 被点击 tabItem 的页面路径
text - 被点击 tabItem 的按钮文字
onTabItemTap(item){
// item.index
// item.pagePath
// item.text
}
其他自定义的事件绑定函数
点我
viewTap(){
console.log('用户点击了 『点我』')
}
Page.route - 到当前页面的路径,类型为 String
Page({
onShow(){
console.log(this.route) // 在 Page 方法内,使用 this 来获取 page 实例
}
})
Page.Prototype.setData(data, callback) - 将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)
1.参数
data - 本次要改变的数据
1>以 'key: value' 的形式表示
2>key 可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如:
array[2].message
a.b.c.d
3>并且不需要在 this.data 中预先定义
callback - setData 引起的界面更新渲染完毕后的回调函数
2.注意
1>直接修改 this.data 而不调用 this.setData 来改变 this.data,是无法改变页面状态的,还会导致数据不一致
2>仅支持设置可 JSON 化数据
3>单次设置的数据,不能超过 1024 KB,尽量避免一次设置过多数据,影响性能
4>不要把 data 中的任何一项的值,设置为 undefined,否则这一项将不被设置,并可能遗留一些潜在的问题
5.getCurrentPages()
获取当前页面栈,数组中的第一个元素为首页,最后一个元素为当前页面
注意:
1>不要尝试修改页面栈,会导致路由及页面状态错误
2>不要在 App.onLaunch() 生命周期函数中调用 getCurrentPages(),此时 page 还没有生成
6.Component()
创建自定义组件
properties - 组件的对外属性,属性名到属性的映射(同 data 一样,也用于渲染组件模板)
data - 组件的内部数据,用于渲染组件模板
observers - 数据字段监听器,用于监听 properties 和 data 的变化
methods - 组件的方法
behaviors - 组件间代码复用(别的语言中,一般叫做:mixins 或 traits)
生命周期函数
created - 组件实例被创建
attached - 组件实例进入页面节点树
ready - 组件布局完成后
moved - 组件实例从当前节点移动到另一个节点
detached - 组件实例从页面节点树移除
relations - 组件间关系定义
externalClasses - 组件接受的外部样式类
options - 一些选项
lifetimes - 组件生命周期对象(和上面的几个生命周期函数一致,推荐以后采用这种方式定义)
pageLifetimes - 组件所在页面的生命周期对象
definitionFilter - 定义段过滤器
/*
具体看:指南 -> 自定义组件
*/
7.Behavior()
注册一个 behavior,用于组件间的代码复用
参数是 Component 里的部分属性,用法一致
8.模块化
module - 当前模块对象(每个 js 文件,都会暴露一个 module 对象)
属性:
exports - 模块向外暴露的对象,使用 'requires' 引用模块时可以获取
exports - module.exports 的引用
require() - 引入模块。返回模块通过 module.exports 或 exports 暴露的对象
示例:
common.js
function getName(name){
return name
}
function getAge(age){
return age
}
module.exports.getName = getName
exports.getAge = getAge
pages/index/index.js
const common = require(../../common.js)
Page({
getName(){
common.getName('dongxuemin')
},
getAge(){
common.getAge(30)
}
})
9.wx.env - 小程序环境变量对象
wx.env.USER_DATA_PATH - 文件系统中的用户目录路径
10.WXML 语法
1>数据绑定
1.内容
{{ message }}
2.组件属性(需要在 ""(双引号) 内) // 和 vue 不同
3.控制属性(需要在 ""(双引号) 内)
4.关键字(需要在 ""(双引号) 内)
/*
true: boolean 类型的 true,代表真值
false: boolean 类型的 false,代表假值
不能直接写: checked="false",其计算结果是一个字符串,转换成 boolean 类型后代表真值
*/
5.运算
1>三元运算
hidden
2>算数运算
{{ a + b }}
3>逻辑判断
4>字符串运算
{{ "hello " + name }}
5>数据路径运算(对象属性、数组元素)
{{ object.name }} {{ array[0] }}
6.组合
1>数组
2>对象
3>对象的 '...' - 扩展运算符
Page({
data: {
user: {
name: 'dongdong',
gender: 'nan',
}
}
})
组合后的对象为:{gender: 'nan', name: 'dongxuemin', age: 30}
注意:
1.出现同名属性,后面覆盖前面
2.对象的 key 和 value 相同,可以简写
原始写法:
简写:
Page({
data: {
name: 'dongxuemin',
age: 30,
user: {
name: 'dongdong',
gender: 'nan',
}
}
})
/*
强调:
{{}} 和 "" 之间如果有空格,将被解析为字符串
等同于
*/
2>列表渲染
wx:for
1.循环项,下标的变量名默认为:index,值的变量名默认为:item
wx:for-index - 指定下标的变量名
wx:for-item - 指定值的变量名
2.wx:key - 来标识循环项的唯一性(vue 也有),有两种形式:
1>字符串 - 在数组中,提供一个属性,来标识唯一,例如:id
2>保留关键字 '*this',表示 '循环项本身'(要求循环项自身是唯一的)
3>条件渲染
wx:if
wx:elif
wx:else
wx:if vs hidden // vue 也有
/*
注意:
这里的 hidden 属性,小程序给每个组件,都提供了一个 hidden 属性,boolean 类型,表示组件是否隐藏
并不是 css 中的 "display: hidden"
*/
4>模板
模板中,可以定义代码片段,然后在页面或组件中引入
1.定义模板
'双标签',并使用 'name' 属性,来作为模板名
{{ error.errno }}
{{ error.errmsg }}
2.使用模板
'单标签',并使用 'is' 属性,声明要使用的模板名,同时传入 'data' 数据
Page({
data: {
error: {
errno: 1,
errmsg: '错误'
}
}
})
/*
is 属性,可以使用 '{{}}' Mustache 语法,从而动态引用 '模板名'
Page({
data: {
tplName: 'error',
}
})
*/
3.模板的作用域
模板拥有自己的作用域,只能通过 'data' 属性来传入模板所需要的数据
5>引用
WXML 有两种文件引入方式:
import
include
1.import
1>import 可以导入其他文件定义的
// error.wxml
{{ error.errno }}
{{ error.errmsg }}
// index.wxml
2>import 的作用域
import 只能导入直接定义在目标文件中的 template,而不能追踪导入
C import B,B import A,在 C 中只可以使用 B 定义的 template,不能使用 A 定义的 template
2.include
include 可以将目标文件中,除了 和 外的所有代码引入,相当于是拷贝到 include 的位置
适合模板布局: