小程序学习笔记 - 框架

提前说下:
	写这两篇笔记,纯看文档,没有实践、测试代码,是否正确,错误的地方可能会很多!只是帮我梳理了下小程序文档。

本笔记,只记录某些重点,或不太清楚的,一般的不做笔记

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>三元运算
				

			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' 属性,来作为模板名

			

		2.使用模板