使用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 相关文章推荐
让任务管理器中的CPU跳舞的js代码
Nov 01 Javascript
JQuery 插件制作实践 xMarquee插件V1.0
Apr 02 Javascript
关于js new Date() 出现NaN 的分析
Oct 23 Javascript
Jquery实现弹出层分享微博插件具备动画效果
Apr 03 Javascript
jquery+ajax+C#实现无刷新操作数据库数据的简单实例
Feb 08 Javascript
jQuery toggle 代替方法
Mar 22 Javascript
BootStrapValidator校验方式
Dec 19 Javascript
bootstrap datetimepicker实现秒钟选择下拉框
Jan 05 Javascript
javascript过滤数组重复元素的实现方法
May 03 Javascript
改变layer confirm弹窗按钮的颜色方法
Sep 12 Javascript
swiper自定义分页器的样式
Sep 14 Javascript
浅谈Vue开发人员的7个最好的VSCode扩展
Jan 20 Vue.js
深入理解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 加密与解密的斗争
2009/04/17 PHP
php访问数组最后一个元素的函数end()用法
2015/03/18 PHP
Yii2框架实现利用mpdf创建pdf文件功能示例
2019/02/08 PHP
php apache开启跨域模式过程详解
2019/07/08 PHP
通过js简单实现将一个文本内容转译成加密文本
2013/10/22 Javascript
jQuery中事件对象e的事件冒泡用法示例介绍
2014/04/25 Javascript
浅析AngularJS Filter用法
2015/12/28 Javascript
jQuery实现的跨容器无缝拖动效果代码
2016/06/21 Javascript
angular4自定义组件详解
2017/09/28 Javascript
vue实现个人信息查看和密码修改功能
2018/05/06 Javascript
javascript使用正则实现去掉字符串前面的所有0
2018/07/23 Javascript
[03:39]DOTA2英雄梦之声_第05期_幽鬼
2014/06/23 DOTA
用python实现的可以拷贝或剪切一个文件列表中的所有文件
2009/04/30 Python
python登陆asp网站页面的实现代码
2015/01/14 Python
Python获取服务器信息的最简单实现方法
2015/03/05 Python
python实现分页效果
2017/10/25 Python
Python实现对字典分别按键(key)和值(value)进行排序的方法分析
2018/12/19 Python
Tensorflow全局设置可见GPU编号操作
2020/06/30 Python
详解python实现可视化的MD5、sha256哈希加密小工具
2020/09/14 Python
如何在网站上添加谷歌定位信息
2016/04/16 HTML / CSS
中粮集团旗下食品网上购物网站:我买网
2016/09/22 全球购物
AC Lens:购买隐形眼镜
2017/02/26 全球购物
英国现代绅士品牌:Hackett
2017/12/17 全球购物
运动鞋、足球鞋和慕尼黑球衣:Sport Münzinger
2019/08/26 全球购物
意大利时尚精品店:Nugnes 1920
2020/02/10 全球购物
大学生创业项目方案
2014/03/08 职场文书
企业标语大全
2014/07/01 职场文书
销售活动策划方案
2014/08/26 职场文书
群众路线剖析材料怎么写
2014/10/09 职场文书
海南召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
优秀教师先进材料
2014/12/16 职场文书
2015年卫生局工作总结
2015/07/24 职场文书
扩展多台相同的Web服务器
2021/04/01 Servers
Pandas搭配lambda组合使用详解
2022/01/22 Python
微信小程序调用python模型
2022/04/21 Python
详细介绍MySQL中limit和offset的用法
2022/05/06 MySQL