We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
持续更新中...
openid = hash(uid + app_id)
unionid = hash(uid + 开放平台id)
关于unionid机制下如何获取用户基本信息,可以参考官方文档:获取用户基本信息(UnionID机制)、UnionID 机制说明
微信小程序的登录流程:
withCredentials
openid的获取方式有两种:
unionid的获取机制可以参考上一节提到的官方文档,下面做一些简要补充。 一般来说,获取unionid可以有两种方式来实现:
用户在首次加载小程序后完成授权,后续再次进入小程序就是静默授权(保有缓存),不会有弹窗授权
目前,在用户首次授权时,微信强制开发者使用调出按钮的方式来引导用户授权。所以,正确的授权方式应该是在页面中定义一个授权弹窗,弹窗上的授权按钮是带有授权功能的,点击后即可完成授权:
授权窗口
<view class="authorize" hidden="{{isShowAuth}}"> <view class="box"> <view class="title">授权登录</view> <view class="content">是否授权获取用户信息</view> <view class="footer"> <button bindtap="cancelAuthroize">取消</button> <button open-type="getUserInfo" bindgetuserinfo="getAuthorize">确定</button> </view> </view> </view>
isHiddenAuth: false getAuthorize() { if (this.data.isShowAuth) { wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用getUserInfo静默授权 this.getUserInfoFromServer(); this.setData({ isShowAuth: false }); } else { // 还未授权,调出弹窗引导用户授权 this.setData({ isShowAuth: true }); } } }) } else { // 如果已经授权就直接登录,在这里可以保存用户信息 } } getUserInfoFromServer() { wx.getUserInfo({ withCredentials: true, success: async res => { // 向后端发出请求,获取openid和unionid const data = await request({ encryptedData: res.encryptedData, iv: res.iv }); // 保存用户信息 app.globalData.userInfo = data; } }); }, cancelAuthroize() { this.setData({ isShowAuth: false, }); app.globalData.userInfo = null; }
微信小程序的生命周期可以大致分为3类,App入口的生命周期,页面的生命周期以及组件的生命周期。
关于onLaunch和onShow的说明: 小程序的启动方式有两种:冷启动和热启动,在用户首次打开小程序的时候,小程序的启动方式就是冷启动,此时会触发onLaunch和onShow回调;当用户将该小程序切至后台,但是并没有被销毁,然后再次打开,小程序的加载时间一般会首次打开的时间更短,此时不会触发onLaunch,但是会触发onShow
Page()
onLoad:监听页面加载 适用场景:页面加载时的初始化操作、获取路由参数。一个页面只会调用一次
onShow:监听页面显示 适用场景:页面显示时的操作。每次页面打开时都会调用一次
onReady:监听页面初次渲染完成 适用场景:页面已经准备妥当,可以和view层进行交互、对页面进行设置(比如设置标题)。一个页面只会调用一次
onHide:监听页面隐藏 适用场景:路由跳转或者底部导航切换时调用、退出页面时关闭一些操作(比如定时器)
onUnload:监听页面卸载 适用场景:底部导航切换时不会触发,路由跳转会触发,退出页面时关闭一些操作(比如定时器)
Component() 组件生命周期可以分为两类:组件内自身的生命周期(在lifetimes属性中定义)和组件在引用页的生命周期(在pageLifetimes)中定义
1.lifetimes:
<component-a wx:for="{{array}}" wx:key="{{item.key}}"></component-a>
2.pageLifetimes:
var wxPromise = function (fn) { return function (opt = {}) { return new Promise((resolve, reject) => { opt.success = function(res) { resolve(res); }; opt.fail = function(res) { reject(res); } fn(opt); }) } } // 使用 var wxRequest = wxPromise(wx.request); wxRequest({ url, param }).then(res => { console.log(res.data); });
在web开发中,我们可以对原生ajax方法或者axios拦截器做一些修改,来实现网络请求的监听。如下:
window.XMLHttpRequest.prototype.open = (originMethod => { return function (method, url, async) { console.log('发送请求,接口是:', url); return originMethod.apply(this, arguments); }; })(window.XMLHttpRequest.prototype.open);
在微信小程序中,我们同样可以通过拦截wx.request方法来实现请求的监听。不过,和上面的方式不一样,我们不能直接对wx.request进行赋值来改写,它只有get方法而没有set方法。所以,我们要用Object.defineProperty来修改:
Object.defineProperty
const originRequest = wx.request; Object.defineProperty(wx, 'request', { configurable: true, enumerable: true, writable: true, valud: function() { const config = arguments[0] || {}; const url = config.url; console.log('发送请求,接口是:', url); return originRequest.apply(this, arguments); } });
function PubSub() { // 订阅列表 this.eventList = null; } // 订阅事件 PubSub.prototype.subscribe = function(eventName, func) { this.initEventList(eventName); this.eventList[eventName].push(func); }; // 移除订阅 PubSub.prototype.unsubscribe = function(eventName, func) { this.initEventlist(eventName); this.eventList[eventName] = this.eventList[eventName].filter(function (item) { return item != func; }); if (!this.eventList[eventName].length) { delete this.eventList[eventName]; } }; // 发布事件 PubSub.prototype.publish = function(eventName, data) { this.initEventList(); if (this.eventName[eventName]) { for (var i = 0, event = this.eventList[eventName]; i < eventList.length; i += 1) { var func = event[i]; func(data); } } }; // 初始化事件列表 PubSub.prototype.initEventList = function(eventName) { if (!this.eventList) { this.eventList = {}; } if (eventName && !this.eventList[eventName]) { this.eventList[eventName] = []; } }; module.exports = PubSub;
使用:
var PubSub = require('../utils/pubSub'); App({ onLaunch: function(e) { // 注册发布订阅模式 event: new PubSub(), } }); // 页面A - 发布 var app = getApp() Page({ publish: function() { app.event.publish('test', 'test') }, }) // 页面B - 订阅 var app = getApp() Page({ onLoad: function(){ app.event.subscribe('test', this.subFunc.bind(this)) }, onUnload: function() { // 移除所有订阅事件 app.event.unsubscribe('test'); // 移除单个订阅事件 app.event.unsubscribe('test', this.subFunc.bind(this)) }, subFunc: function(param) { // 监听事件 console.log(param) }, })
微信小程序通过自带API设置的客户端缓存是不存在有效期的概念的,长期有效,如果需要设置带有效期的缓存,就需要同时对一个目标同时设置目标本身的数据,以及对应自身的设置时间:
// 基本原理:通过微信官方的API分别对数据进行两份缓存,一份是原数据的缓存,另外一份是对应的时间进行缓存,时间缓存中带有原数据的key值 class Storage { constructor(props) { this.props = props || {}; this.source = wx || this.props.source; } /** * 获取缓存 * @param {String} key key值 * @return 缓存内容 */ getStorage(key) { const timeout = parseInt(this.source.getStorageSync(`${key}__time`) || 0, 10); // 有对应的时间缓存 if (timeout) { // 如果超出时间 if (Date.now() > timeout) { this.removeStorage(key); return; } } const value = this.source.getStorageSync(key); return value; } /** * 设置缓存 * @param {String} key key值 * @param value value值 * @param {Number} timeout 过期时间 * @return value */ setStorage(key, value, timeout = 0) { const _timeout = parseInt(timeout, 10); this.source.setStorageSync(key, value); if (_timeout) { this.source.setStorageSync(`${key}__time`, Date.now() + 1000 * 60 * _timeout); } else { this.source.removeStorageSync(`${key}__time`); } return value; } removeStorageSync(key) { this.source.removeStorageSync(key); this.source.removeStorageSync(`${key}__time`); return undefined; } } const storage = new Storage(); wx.$storage = storage; export default storage;
参考:
The text was updated successfully, but these errors were encountered:
一些在前端开发中通用的优化策略就不谈了,主要是针对小程序这种特殊情况的。
小程序主包的大小限制为2M,超过该大小后无法上传。所以,对于一些较为独立的业务功能,应该考虑分包开发,分包的文件不会占用主包的空间。
通过setData设置的数据,是小程序数据层和视图层的中间介质。微信开发者文档上有这么一句话:
小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。 而 evaluateJavascript 的执行会受很多方面的影响,数据到达视图层并不是实时的。
大量数据、频繁地setData,会增加数据层和视图层通信的压力,影响小程序的性能。所以,对于setData的操作,我们应该要有以下的基本准则:
官方文档上也提供了一些关于setData的优化tips,可以参考: https://developers.weixin.qq.com/miniprogram/dev/framework/performance/tips.html
补充说明: 不要用setData将data值设置为undefined,否则可能会出现一些问题(控制台也会警告)
前面提到了数据层和视图层的通信问题,实际上可以展开为,不仅仅是setData,一切涉及到此类通信的问题都需要谨慎考虑数据的大小和设置频率。比如,wxml中的dataset属性,最好也是不要绑定数据大的复杂对象;减少事件绑定......
对于频繁触发的事件,要做好防抖或节流的控制,比如在onPageScroll中,每次滚动都会触发该事件,如果在里面直接进行setData,是一件恐怖的事。
onPageScroll
wxs的执行效率比js高,所以data中的一些数据操作可以考虑在wxs中处理。
Sorry, something went wrong.
No branches or pull requests
小程序开发记录
持续更新中...
微信体系的一些基本概念
openid = hash(uid + app_id)
在未关注公众号时,访问公众号网页也会产生一个用户和对应的公众号唯一openid。它可以用来标识用户身份
unionid = hash(uid + 开放平台id)
unionid可以看作是各个openid的集合,如果开发者拥有多个公众号或小程序,那么用户在各个公众号或小程序中都有一个openid,如果要在多个产品中进行账号互通,可以使用unionid来实现。只要在同一个微信开放平台账号下的公众号,用户的unionid就是唯一的。
关于unionid机制下如何获取用户基本信息,可以参考官方文档:获取用户基本信息(UnionID机制)、UnionID 机制说明
微信小程序的登录流程:
微信授权和开发功能
withCredentials
要设置为true才可以获取加密数据encryptedData和加密算法的初始向量iv注意:为了维护系统的安全,临时code可以返回给前端,但是session_key是不可以对外的
关于如何获取openid和unionid
openid的获取方式有两种:
unionid的获取机制可以参考上一节提到的官方文档,下面做一些简要补充。
一般来说,获取unionid可以有两种方式来实现:
前面提到过,同一个开发平台下注册的公众号和小程序的单个用户的unionid是一样的,所以,假如用户已经在其他同主体的公众号或小程序登录了,那么可以直接通过wx.login + code2Session方式获取该用户的unionid
用户在首次加载小程序后完成授权,后续再次进入小程序就是静默授权(保有缓存),不会有弹窗授权
开发者如何正确调用授权
目前,在用户首次授权时,微信强制开发者使用调出按钮的方式来引导用户授权。所以,正确的授权方式应该是在页面中定义一个授权弹窗,弹窗上的授权按钮是带有授权功能的,点击后即可完成授权:
授权窗口
微信小程序生命周期
微信小程序的生命周期可以大致分为3类,App入口的生命周期,页面的生命周期以及组件的生命周期。
App函数是整个小程序的入口,它的生命周期如下:
关于onLaunch和onShow的说明:
小程序的启动方式有两种:冷启动和热启动,在用户首次打开小程序的时候,小程序的启动方式就是冷启动,此时会触发onLaunch和onShow回调;当用户将该小程序切至后台,但是并没有被销毁,然后再次打开,小程序的加载时间一般会首次打开的时间更短,此时不会触发onLaunch,但是会触发onShow
Page()
onLoad:监听页面加载
适用场景:页面加载时的初始化操作、获取路由参数。一个页面只会调用一次
onShow:监听页面显示
适用场景:页面显示时的操作。每次页面打开时都会调用一次
onReady:监听页面初次渲染完成
适用场景:页面已经准备妥当,可以和view层进行交互、对页面进行设置(比如设置标题)。一个页面只会调用一次
onHide:监听页面隐藏
适用场景:路由跳转或者底部导航切换时调用、退出页面时关闭一些操作(比如定时器)
onUnload:监听页面卸载
适用场景:底部导航切换时不会触发,路由跳转会触发,退出页面时关闭一些操作(比如定时器)
Component()
组件生命周期可以分为两类:组件内自身的生命周期(在lifetimes属性中定义)和组件在引用页的生命周期(在pageLifetimes)中定义
1.lifetimes:
<component-a wx:for="{{array}}" wx:key="{{item.key}}"></component-a>
里面的顺序修改2.pageLifetimes:
请求Promise化
监控或埋点
拦截请求
在web开发中,我们可以对原生ajax方法或者axios拦截器做一些修改,来实现网络请求的监听。如下:
在微信小程序中,我们同样可以通过拦截wx.request方法来实现请求的监听。不过,和上面的方式不一样,我们不能直接对wx.request进行赋值来改写,它只有get方法而没有set方法。所以,我们要用
Object.defineProperty
来修改:使用发布订阅模型来进行全局事件通信
使用:
小程序设置缓存有效期
微信小程序通过自带API设置的客户端缓存是不存在有效期的概念的,长期有效,如果需要设置带有效期的缓存,就需要同时对一个目标同时设置目标本身的数据,以及对应自身的设置时间:
参考:
The text was updated successfully, but these errors were encountered: