小程序学习笔记 - 指南

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

笔记个别重点:
	1.自定义组件
		Component 构造器,该页面的 Component() 方法的参数并不全,需要看的是:
			框架 -> 框架接口 -> 自定义组件 -> Component

	2.多线程
		1>app.json 中配置 'Worker' 代码放置的目录
			{
				"workers": "workers"
			}

		2>在上面定义的目录下,我们就可以创建我们想要的 worker 线程文件(任意创建,也可以创建其他文件,例如:utils.js)
			workers/index.js
			workers/utils.js
			workers/request/index.js
			workers/response/index.js
			...

		3>编写 worker 线程文件,例如:workers/request/index.js
			const utils = require('../utils.js')

			// worker 线程文件,会自动暴露一个 'worker' 对象,我们直接使用即可
			// (worker 线程文件有一个 worker 对象,我们直接使用)

			// 1.接收消息(接收主线程的消息)
			worker.onMessage(function(res){
				console.log(res)
			})

			// 2.发送消息(给主线程发送消息)
			worker.postMessage({
				msg: '你好,主线程'
			})

		4>在主线程,初始化我们定义好的 worker 线程(主线程就是目前的微信小程序线程,可以理解为在 app.js 文件中)

			// 参数为:我们定义的 worker 线程文件(绝对路径)
			const worker = wx.createWorker('workers/request/index.js')	

			// 1.主线程向 worker 线程发送消息
			worker.postMessage({
				msg: '你好,worker 线程'
			})

			// 2.主线程接收 worker 线程的消息
			worker.onMessage(function(res){
				console.log(res);
			})

			// 3.worker 线程的最大并发数量为 1,所以,要切换其他 worker 线程,需要结束之前创建的 worker 线程
			// (只有主线程可以调用)
			worker.terminate()

		5>注意点:
			1.worker 线程最大并发数量为 1,创建另外线程,需结束之前的线程
			2.worker 文件中,只能 require 我们定义的 worker 目录下的文件
			3.worker 内不支持 wx 系列的 API

	3.服务端能力
		1>服务端 API

		2>消息推送
			类似我们之前开发的微信公众号的消息系统(消息和事件)

	4.自定义 tabBar
		如果我们不想要小程序默认的 'tabBar',我们可以使用 '自定义 tabBar' 来接管。所有 tabBar 的页面,只能使用同一个 '自定义 tabBar'。(这个也是正确的)

		对于我们可能希望,不同的大的模块内部,也有自己的 '底部导航',我们可以当做页面的底部(这种并非是 'tabBar',不过非常类似),就是正常的页面结构就可以了,只不过模拟成 tabBar 的感觉。

		'自定义 tabBar' 需要配置:
			1>app.json 中指定 『"custom": true』,表示使用 '自定义 tabBar'

			2>其余的 tabBar 配置项,依旧得完整填写,为了兼容旧版。

			3>所有的 tab 页,还需配置『"usingComponents": {}』,简单的写法是,直接在 app.json 中配置 『"usingComponents": {}』(不过不推荐,不清晰)

	5.优化
		1>setData 原理
			WebView(视图层) 和 JavascriptCore(逻辑层),都是独立的模块,不具备数据直接共享的通道,两边是通过 evaluateJavascript 实现。

			evaluateJavascript 实现是:将用户传输的数据,转为 '字符串' 进行传递,传递完成后,再拼接成 'js 脚本',然后执行 'js 脚本' 来达到数据传递。

			所以 setData 不能过于频繁、不能单次传递大量数据,同时,页面进入后台,不可进行 setData。

		2>图片资源
			大图片和长列表图片(很长的列表页,列表中的每项,都带有图片),对内存和页面切换,都有很大影响
				https://sevencai.github.io/2018/03/22/%E9%95%BF%E5%88%97%E8%A1%A8%E5%9B%BE%E7%89%87%E4%BC%98%E5%8C%96%E6%96%B9%E5%BC%8F/

				再次链接到了 '张鑫旭' 博客了,好久没看他的文章了...
					https://www.zhangxinxu.com/php/myRecomm

				'掘金' 看来也不错,有时间看看
					https://juejin.im/

		3>代码包大小
			1.尽量不包含图片,放到 CDN
			2.及时清理不用的代码,类库引用等都得注意

	6.调试
		1>vConsole

		2>Source Map(方便排错,同时只作用域 '开发版',无需担心 '线上版')
			在开发者工具中开启 ES6 转 ES5、代码压缩时,会生成 Source Map 的 .map 文件。开发版小程序中,基础库会使用代码包中的 .map 文件,对 vConsole 中展示的错误信息堆栈进行重新映射

	7.低版本兼容
		1>版本号比较	
			1.微信客户端和小程序基础库的版本号风格为:Major.Minor.Patch(主版本号.次版本号.修订版本号)

			2.组件、API等,都有要求的 '最低基础库版本号',判断当前版本号是否达到要求,达不到需进行处理,是否升级等

			3.通过 wx.getSystemInfo 或 wx.getSystemInfoSync 的 SDKVersion 来获取当前小程序运行的基础库的版本号

			4.版本号比较,不要直接使用 '字符串比较'。官方给我们提供了一个 compareVersion() 函数,看文档

		2>API 存在判断
			对于新增的 API,可以判断 API 是否存在,来进行兼容处理
				if(wx.openBluetoothAdapter){
					//存在
				}else{
					// 不存在
				}

		3>wx.canIUse
			通过 wx.canIUse,可以判断以下内容,是否可以在当前版本的基础库使用
			1.API 参数或返回值的参数
				wx.showModal({
					success(res){
						if(wx.canIUse('showDodal.cancel')){
							// 可以使用
						}
					}
				})

			2.组件或组件的属性
				wx.canIUse('cover-view')

		4>小程序后台,可以设置 '基础库最低版本',强制用户来升级 '微信客户端'

	8.转发
		1>2种方式:
			1.右上角转发菜单
			2.页面内转发按钮
				

		2>必须设置页面的 Page.onShareAppMessage() 事件,它监听用户转发的行为,并自定义转发内容
			onShareAppMessage(res){
				// res.from - 转发事件来源(button - 页面内转发按钮 | menu - 右上角转发菜单)
				// res.target - from 的值是 button,target 为转发按钮 

				open-type 为 contact,可用的属性有:

					session-from - 会话来源(用户进入客服会话,发送的 '事件消息' 的 SessionFrom 参数)

					send-message-title - 会话内消息卡片标题(默认:当前标题)

					send-message-path - 会话内消息卡片点击跳转小程序路径(默认:当前分享路径)

					send-message-img - 会话内消息卡片图片(默认:当前页面截图)

					show-message-card - 是否显示会话内消息卡片,设置为 true,用户进入客服会话会在右下角显示 '可能要发送的小程序' 提示,用户点击后,可以快速发送小程序消息(默认:false)

					bindcontact - 客服消息回调
						如果用户在会话中点击了小程序消息,则会返回到小程序,我们可以通过 bindcontact 事件回调,获取用户所点消息的页面路径 path 和对应的参数 query

						/*
							这里提到了:用户在会话中,点击了 '小程序消息'。
							小程序消息来源:
								1>我们后台可以给用户,发送 '小程序类型的消息'

								2>上面的几个 '*-message-*' 属性,其实就定义了 '小程序消息',而不需要后台发送(相当于前台发送了)
						 */

						page({
							handleContact(e){
								// e.path 
								// e.query
							}
						})


			2.在微信的 '小程序客服消息' 列表中,进入指定的 '小程序' 的客服消息

		2>用户主动发送消息
			1.文本消息
				MsgType - text
				Content - 文本内容

			2.图片消息
				MsgType - image
				PicUrl - 图片链接(由系统生成)
				MediaId - 图片消息媒体id,可以调用 getTempMedia 接口来获取图片内容

			3.小程序卡片消息	
				MsgType - miniprogrampage
				Title - 标题
				AppId - 小程序 appid
				PagePath - 小程序页面路径
				ThumbUrl - 封面图片的临时 cdn 链接
				ThumbMediaId - 封面图片的临时素材 id(应该跟 image 消息的 MediaId 一样,可以通过接口获取图片内容)

		3>用户触发事件消息
			1.用户在页面中,点击 '客服会话按钮' 进入客服会话,触发事件
				MsgType - event
				Event - user_enter_tempsession
				SessionFrom - sessionFrom(开发者在客服会话按钮设置的 session-from 属性)

		4>服务器给用户发送消息
			不能主动给用户发送客服消息,只有当用户和小程序客服产生特定动作交互时,开发者才可给用户发送消息。
			目前允许的动作有:
				用户发送消息 - 允许服务器向用户 | 下发条数限制 - 5 | 下发时限 - 48小时

			1.文本消息
				msgtype - text
				text: {
					content - 文本内容
				}

				// 发送文本消息,支持添加可跳转小程序的文字链接(在网上搜了下,没人知道怎么实现...)
				/*
					点击下方,跳转到我的小程序(这里是我们的文本内容)
					
						点击跳小程序
					
				 */

			2.图片消息
				msgtype - image
				image: {
					media_id - 图片媒体id,通过 '新增素材接口' 上传图片文件获得
				}

			3.图文链接
				msgtype - link
				link: {
					title - 消息标题
					description - 描述
					url - 消息被点击后跳转的链接
					thumb_url - 图片链接,支持 jpg、png,较好的效果为,大图 - 640x320 | 小图 - 80x80
				}

			4.小程序卡片
				msgtype - miniprogrampage
				miniprogrampage: {
					title - 消息标题
					pagepath - 小程序的页面路径,跟 app.json 对齐,支持参数,例如:pages/index/index?foo=bar
					thumb_media_id - 小程序消息卡片的封面,image 类型的 media_id,由 '新增素材接口' 上传图片文件获得,建议大小为:520x416
				}

		5>转发客服消息
			不太懂...

		6>下发客服输入状态
			就是在客服消息页面中,给用户展示 '正在输入'

			服务端 -> 客服消息 -> customerServiceMessage.setTyping

			参数:
				access_token
				touser - 用户的 openId
				command - 命令
					Typing - 对用户下发 '正在输入' 状态
					CancelTyping - 取消对用户的 '正在输入' 状态

		7>临时素材
			开发者可在接收和发送客服消息的过程中,获取或上传临时素材

			1.获取客服消息内的临时素材(下载临时的多媒体文件)
				服务端 -> 客服消息 -> customerServiceMessage.getTempMedia	

				参数:
					access_token
					media_id - 媒体文件 id

			2.上传媒体文件(用于发送客服消息,或被动恢复用户消息)
				服务端 -> 客服消息 -> customerServiceMessage.uploadTempMedia	

				参数:
					access_token
					type - 文件类型(目前只有 image)
					media - FormData,form-data 中媒体文件标识,有 filename、filelength、content-type 等信息

	12.生成小程序码
		1>小程序码的优势:
			1.具有更好的辨识度,美观
			2.拥有展示 '公众号关注组件' 等高级能力
				组件 -> 开放能力 -> official-account
					当用户扫 '小程序码' 打开小程序时,开发者可在小程序内配置 '公众号关注组件',方便用户快捷关注公众号。

					几点注意事项:
						1.设置的公众号需要和小程序在同一个主体下
						2.组件限定最小宽度为 300px,高度为 84px
						3.每个页面只能配置一个该组件(类似页面上的一个 view 结构)

				
				属性:
					bindload - 组件加载成功时触发
					binderror - 组件加载失败时触发

		2>生成 '小程序码' 接口
			1.适用于需要的码数量较少的业务场景。永久有效,和 wxacode.createQRCode 生成的二维码总数限制 100000 个
				服务端 -> 小程序码 -> wxacode.get

				参数:
					access_token
					page - 
					width - 
					auto_color - 
					line_color - 
					is_hyaline - 

			2.适用于需要的码数量极多的业务场景。永久有效,数量暂无限制
				服务端 -> 小程序码 -> wxacode.getUnlimited

				参数:
					access_token
					scene - 
					page - 
					width - 
					auto_color - 
					line_color - 
					is_hyaline - 

		3>生成 '小程序' 的 '二维码' 接口(这个接口专门单独出来,是生成普通的二维码,并非是 '小程序码',没有上面提到的优势)
			1.适用于需要的码数量较少的业务场景。永久有效,和 wxacode.get 生成的二维码总数限制 100000 个
				服务端 -> 小程序码 -> wxacode.createQRCode

				参数:
					access_token
					page - 
					width - 

	13.小程序登录
		小程序可以通过微信官方提供的登录能力,方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系

		登录流程分 2 步:
			1.小程序前端,调用 wx.login() API,来获取临时登录凭证 code
				API -> 开放接口 -> 登录 -> wx.login

				wx.login
					参数:
						timeout - 超时时间
						success - 
						fail - 
						complete - 

					sucess 回调函数的参数:
						code - 用户登录凭证(有效期:5分钟)

				/*
					还有一个相关的接口:
						wx.checkSession() - 检查登录态是否过期

						参数:
							success - 
							fail - 
							complete - 

						很多时候,需要 session_key 来进行解密,如果 session_key 过期,会导致失败。我们需要判断用户是否仍旧登录着,不登录则重新登录

						wx.checkSession({
							success(){
								// 出于登录状态
							},
							fail(){
								// session_key 已过期,需要重新登录
								wx.login()
							}
						})
				 */

			2.通过上面获取到的 code,请求我们的开发服务器,开发服务器调用 '服务端接口' 的 'auth.code2Session',换取用户唯一标识 'open_id' 和 会话秘钥 'session_key'
				服务端 -> 开发接口 -> 登录 -> code2Session

				code2Session
					get https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

					请求参数:
						appid - 小程序 appId
						secret - 小程序 appSecret
						js_code - wx.login() 得到的 code
						grant_type - 授权类型,目前只有:authorization_code

					返回值:
						openid - 用户 open_id
						session_key - 会话秘钥
						unionid - 用户 unionid,微信开放平台绑定了小程序
						errcode - 错误码
						errmsg - 错误信息

		注意:
			1.会话秘钥 session_key 是对用户数据进行 '机密签名' 的秘钥。为了安全,需要保存在服务器。

			2.临时登录凭证 code 只能使用一次

		/*
			考虑:
				1.上面的登录流程,是微信的登录流程,并未对接到我们的业务系统用户,我们还需要和业务系统的用户进行绑定关联!
					user_binds - 用户绑定表
						id
				        user_id - 用户id
				        type - 类型:qq、aliyun、wechat_official_account、wechat_miniprogram
				        unique_identifier - unionid
				        attach_identifier - openid
				        nick_name - 昵称
				        gender - 性别
				        ...

				session_key 也得保存,用于解密,只有临时数据,redis 中比较合适,和 open_id 关联上就行

				2.我们的系统,是否应该采用微信这套 '登录状态' 体系?
					我感觉不太合适,还是后端来存储比较合适。小程序只是提供一个快捷入口,直接登录,首次需要和用户 id 绑定下,以后就关联登录了
		 */

	14.授权
		部分接口需要经过用户授权同意后,才能使用。
			1>如果用户未接受或拒绝过此权限,会弹窗询问用户,用户点击同意后方可调用接口
			2>如果用户已授权,可以直接调用接口
			3>如果用户已拒绝授权,则不会出现弹窗,直接进入接口 fail 回调(我们需要做用户拒绝授权的处理)

		1>获取用户授权设置
			API -> 设置 -> wx.getSetting

			获取用户的当前设置(返回值中,只会出现小程序已经向用户请求过的权限 - 这个意思是,我们项目里可能涉及了好多授权的权限,但是用户目前只访问到其中的部分,就只会显示这部分的权限)

			wx.getSetting({
				success(res){
					res.authSetting = {
						"scope.userInfo": true,
						"scope.userLocation": true,
					}	
				}
			})

		2>打开设置界面
			打开设置界面有 2 种方式:
				1.小程序设置界面:「右上角」 - 「关于」 - 「右上角」 - 「设置」

				2.开发者可以调用 wx.openSetting 打开设置界面
					/*
						参考:https://developers.weixin.qq.com/community/develop/doc/000cea2305cc5047af5733de751008
						之前,可以直接调用该接口,后来微信为了避免此接口的滥用,调整了调用方式:
							1>使用 

							2>由点击行为,触发 wx.openSetting 接口
								
								Page({
									openSetting(e){
										wx.openSetting()	
									}
								})
					 */

			// 参数&返回结果和 'wx.getSetting' 一致
			wx.openSetting({
				success(res){
					res.authSetting = {
						"scope.userInfo": true,
						"scope.userLocation": true,
					}	
				}
			})

		3>发起用户授权
			API -> 授权 -> wx.authorize

			提前向用户发起授权请求。调用后,会立刻弹窗询问用户是否同意授权。如果之前已同意授权,则不会出现弹窗,直接返回成功

			wx.authorize({
				// scope - 需要获取权限的 scope
				// success - 成功
				// fail - 失败
				// complete - 成功、失败都执行
			})

		4>scope 列表
			scope.userInfo - 用户信息(接口:wx.getUserInfo)
			scope.userLocation - 地理位置(接口:wx.getLocation, wx.chooseLocation)
			scope.address - 通讯地址(接口:wx.chooseAddress)
			scope.invoiceTitle - 发票抬头(接口:wx.chooseInvoiceTitle)
			scope.invoice - 获取发票(接口:wx.chooseInvoice)
			scope.werun - 微信运动步数(接口:wx.getWeRunData)
			scope.record - 录音功能(接口:wx.startRecord)
			scope.writePhotosAlbum - 保存到相册(接口:wx.saveImageToPhotosAlbum, wx.saveVideoToPhotosAlbum)
			scope.camera - 摄像头( 组件)

			注意:
				1.wx.authorize({ scope: "scope.userInfo" }) 	// 不会出现授权窗口,需要使用 

				2.scope.userLocation,必须配置 '地理位置说明用途'
					/*
						框架 -> 小程序配置 -> 全局配置 -> permission
						  	"permission": {
							    "scope.userLocation": {
							    	"desc": "小程序获取权限时展示的接口用途说明,最长 30 个字符"
						    	}
					    	}
					 */

		5>AuthSetting
			用户授权设置信息

			wx.getSetting({
				success(res){

					// 返回 authSetting,
					// res.authSetting

					// 是否授权了 '录音功能'
					if( ! res.authSetting['scope.record']){

					}
				}
			})

			{
				"scope.userInfo": true,
				"scope.userLocation": true,
				...
				对应上面的 scope 列表
				...
			}


	15.获取手机号
		1>调用须知
			1.获取微信用户绑定的手机号,需要先调用 'wx.login' 接口

			2.需要用户主动触发,才能发起获取手机的接口。所以不能通过 API 调用,得使用 '

			2.在 '事件回调' 中,通过微信返回的加密数据,调用开发服务器的接口,结合服务器上存储的 session_key 和 app_id 来解密数据,得到用户手机号(需要 session_key,所以之前必须调用了 'wx.login')
				Page({
				  	getPhoneNumber(e) {
					    console.log(e.detail.errMsg)
					    console.log(e.detail.iv)
					    console.log(e.detail.encryptedData)

					    // 调用服务器接口
					    wx.request({

					    })
				  	}
				})

				/*
					注意:
						在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。
						建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态。
				 */

		3>返回参数说明
			encryptedData - 包括敏感数据在内的完整用户信息的加密数据

			iv - 加密算法的初始向量

			encryptedData 解密后的 json 结构为:
				{
				  	"phoneNumber": "13580006666", 		// 用户绑定的手机号(国外手机号会有区号)
				  	"purePhoneNumber": "13580006666",	// 没有区号的手机号
				  	"countryCode": "86", 				// 区号
				  	"watermark": {
				    	"appid": "APPID",
				    	"timestamp": TIMESTAMP
				  	}
				}


 

你可能感兴趣的:(微信小程序)