使用watch在微信小程序中实现全局状态共享


Posted in Javascript onJune 03, 2019

问题

在之前开发微信小程序的时候,获取用户信息、openid还有地理位置这些信息的时候,都是采用Promise的方式异步获取,但是这样的话在页面和App.js中都获取就可能造成请求重复的问题。

比如为了在每个页面都能获取到这些共享信息,都会选择在App.js中进行获取,然后在页面级进行获取,这两次获取的时间间隔较小时就可能导致前一个请求还未获取到数据,后一个请求就会再次进行获取,这样就产生了两次请求。

还有一个问题就是书写麻烦(虽然也能通过async await简化),比如

onLoad() {
 app.getUserInfo()
 .then(userInfo => {
 
 }).catch(err => { /* 错误处理 */ });
 
 // 如果同时需要userInfo和openid,可能就是如下形式:
 Promise.all([app.getUserInfo(), app.getOpenid()])
 .then(res => {
 
 }).catch(err => { /* 错误处理 */ });
}

正好周末的时候突然想到了vue的watch语法,利用一些相关的知识,就可以解决这个麻烦的问题了。

解决思路

双向绑定

vue的双向绑定原理,3.0将会采用Proxy监听数据变化,不过考虑到小程序这边的Proxy兼容性我不知道,所以采用了2.0的Object.defineProperty来监听数据的变化。

主要还是拦截设置的操作,在进行赋值时,将新旧值通知至监听者。

观察者模式

在页面级的onLoad监听app.globalData各个键名的事件,而在app.js的onLoad中则使用Object.defineProperty重新定义app.globalData,这样一旦app.globalData相应的键值发生了变化,就会通知监听的页面该值发生了变化。

模块化的引用

观察者模式导出的是一个对象(类实例),而不是一个类,所以在导入的时候这个对象是共享的,就可以通过这个对象将app.js和其他页面联系起来。

至于模块加载的实质,ES6模块加载的机制,与CommonJS模块完全不同。感兴趣的可以去看看这个。

封装Page

小程序的Page函数本身是不支持watch,但是我们可以自定义一个函数,进行参数合并就可以了。

在页面onLoad时先遍历watch属性,对app.globalData进行监听,可以参考vue的watch用法。

页面onUnload时就会进行销毁,此时也应该取消监听,这些我都封装过了,不用手动处理了。

有了这些思路,用不了多久,一个雏形就出来了,经过手动测试,感觉没什么问题,我就发布到npm了,大家感兴趣的可以安装体验一下。

安装

npm i wx-watch -S --production

使用

// app.js
var { watchData, } = require('/miniprogram_npm/wx-watch/index.js');

App({
 onLaunch() {
 this.watchData(); /* 监听this.globalData的变化,并触发事件,其他页面监听的值必须在globalData中预先定义,否则无法监听 */
 },
 watchData,
 globalData: {
 userInfo: null,
 }
});

// 其他需要监听globalData的页面.js
var { getPage } = require('../../miniprogram_npm/wx-watch/index.js');
const app = getApp();

/**
 * getPage(页面参数,app) app必传,因为封装的时候访问不到,就只能传参了
*/
getPage({
 watch: {
 userInfo(userInfo, oldUserInfo) {
 console.log(`来自app.glodalData的userInfo`);
 }
 },
 // 其他参数
}, app)

github:  github.com/ma125120/wx…

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JAVASCRIPT IE 与 FF中兼容问题小结
Feb 18 Javascript
JavaScript.The.Good.Parts阅读笔记(一)假值与===运算符
Nov 16 Javascript
30个精美的jQuery幻灯片效果插件和教程
Aug 23 Javascript
javascript进行数组追加方法小结
Jun 16 Javascript
JS使用for循环遍历Table的所有单元格内容
Aug 21 Javascript
js点击列表文字对应该行显示背景颜色的实现代码
Aug 05 Javascript
HTML5 实现的一个俄罗斯方块实例代码
Sep 19 Javascript
jquery append与appendTo方法比较
May 24 jQuery
微信小程序实现图片上传功能实例(前端+PHP后端)
Jan 10 Javascript
mpvue写一个CPASS小程序的示例
Sep 04 Javascript
JavaScript对象的特性与实践应用深入详解
Dec 30 Javascript
Element ui 下拉多选时新增一个选择所有的选项
Aug 21 Javascript
深入理解JS异步编程-Promise
Jun 03 #Javascript
模块化react-router配置方法详解
Jun 03 #Javascript
react 组件传值的三种方法
Jun 03 #Javascript
angular使用md5,CryptoJS des加密的方法
Jun 03 #Javascript
Node.js 的 GC 机制详解
Jun 03 #Javascript
微信小程序蓝牙连接小票打印机实例代码详解
Jun 03 #Javascript
react-native滑动吸顶效果的实现过程
Jun 03 #Javascript
You might like
测试php函数的方法
2013/11/13 PHP
php使用curl打开https网站的方法
2015/06/17 PHP
背景音乐每次刷新都可以自动更换
2007/02/01 Javascript
从阿里妈妈发现的几个不错的表单验证函数
2007/09/21 Javascript
EXTjs4.0的store的findRecord的BUG演示代码
2013/06/08 Javascript
js中创建对象的几种方式示例介绍
2014/01/26 Javascript
Linux下使用jq友好的打印JSON技巧分享
2014/11/18 Javascript
node.js中的url.format方法使用说明
2014/12/10 Javascript
Javascript动态创建表格及删除行列的方法
2015/05/15 Javascript
jQuery拖拽通过八个点改变div大小
2020/11/29 Javascript
详解动画插件wow.js的使用方法
2017/09/13 Javascript
Vue 幸运大转盘实现思路详解
2019/05/06 Javascript
Python中的异常处理简明介绍
2015/04/13 Python
Python实现线程池代码分享
2015/06/21 Python
浅谈插入排序算法在Python程序中的实现及简单改进
2016/05/04 Python
关于python的list相关知识(推荐)
2017/08/30 Python
Python多进程并发与多线程并发编程实例总结
2018/02/08 Python
python实现图片识别汽车功能
2018/11/30 Python
python实现雪花飘落效果实例讲解
2019/06/18 Python
python打造爬虫代理池过程解析
2019/08/15 Python
Python OpenCV实现测量图片物体宽度
2020/05/27 Python
解决Keras 自定义层时遇到版本的问题
2020/06/16 Python
Python自动巡检H3C交换机实现过程解析
2020/08/14 Python
python字符串拼接+和join的区别详解
2020/12/03 Python
总务岗位职责
2013/11/19 职场文书
餐厅采购员岗位职责
2014/03/06 职场文书
教师求职自荐书
2014/06/14 职场文书
简单租房协议书范本
2014/08/20 职场文书
民主评议党员总结
2014/10/20 职场文书
开票员岗位职责
2015/02/12 职场文书
综合测评自我评价
2015/03/06 职场文书
《从现在开始》教学反思
2016/02/16 职场文书
《七月的天山》教学反思
2016/02/19 职场文书
如何用python清洗文件中的数据
2021/06/18 Python
SQL实现LeetCode(176.第二高薪水)
2021/08/04 MySQL
分享提高 Python 代码的可读性的技巧
2022/03/03 Python