使用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 特殊字符串
Feb 25 Javascript
javascript学习笔记(十八) 获得页面中的元素代码
Jun 20 Javascript
Javascript图像处理—平滑处理实现原理
Dec 28 Javascript
jquery统计用户选中的复选框的个数
Jun 06 Javascript
JavaScript 获取任一float型小数点后两位的小数
Jun 30 Javascript
JS简单生成两个数字之间随机数的方法
Aug 03 Javascript
jQuery解决input元素的blur事件和其他非表单元素的click事件冲突问题
Aug 15 Javascript
关于JavaScript数组你所不知道的3件事
Aug 24 Javascript
微信小程序 删除项目工程实现步骤
Nov 10 Javascript
jQuery动态生成表格及右键菜单功能示例
Jan 13 Javascript
vue用BMap百度地图实现即时搜索功能
Sep 26 Javascript
解决vue中provide inject的响应式监听
Apr 19 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
2020年4月新番动漫目录 官方宣布4月播出的作品一览
2020/03/08 日漫
建站常用13种PHP开源CMS比较
2009/08/23 PHP
PHP随机生成随机个数的字母组合示例
2014/01/14 PHP
php实现批量压缩图片文件大小的脚本
2014/07/04 PHP
IIS 7.5 asp Session超时时间设置方法
2017/04/17 PHP
[原创]PHP正则删除html代码中a标签并保留标签内容的方法
2017/05/23 PHP
php时间戳转换代码详解
2019/08/04 PHP
一些常用的JS功能函数代码
2009/06/23 Javascript
JavaScript实现模仿桌面窗口的方法
2015/07/18 Javascript
angular.extend方法的具体使用
2017/09/14 Javascript
form表单数据封装成json格式并提交给服务器的实现方法
2017/12/14 Javascript
使用javascript做在线算法编程
2018/05/25 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
Vue2 添加数据可视化支持的方法步骤
2019/01/02 Javascript
ES6 如何改变JS内置行为的代理与反射
2019/02/11 Javascript
Vue+Bootstrap实现简易学生管理系统
2021/02/09 Vue.js
跟老齐学Python之有点简约的元组
2014/09/24 Python
用Python写一个无界面的2048小游戏
2016/05/24 Python
浅谈Django自定义模板标签template_tags的用处
2017/12/20 Python
python xpath获取页面注释的方法
2019/01/14 Python
python基于itchat模块实现微信防撤回
2019/04/29 Python
Python3实现定时任务的四种方式
2019/06/03 Python
Pandas中resample方法详解
2019/07/02 Python
使用selenium和pyquery爬取京东商品列表过程解析
2019/08/15 Python
python-Web-flask-视图内容和模板知识点西宁街
2019/08/23 Python
详解用selenium来下载小姐姐图片并保存
2021/01/26 Python
韩国现代百货官网:Hmall
2018/03/21 全球购物
学习十八大报告感言
2014/02/04 职场文书
教育英语专业毕业生的求职信
2014/03/13 职场文书
应届生求职自荐信范文
2014/04/07 职场文书
运动会通讯稿200字
2015/07/20 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
六年级情感作文之500字
2019/10/23 职场文书
导游词之永泰公主墓
2019/12/04 职场文书
redis复制有可能碰到的问题汇总
2022/04/03 Redis
Golang解析JSON对象
2022/04/30 Golang