小程序页面通信
解决方案有很多,本地缓存、全局变量、手写订阅发布。本文着重介绍另一个解决方案,就是暂存当前页面的执行上下文,然后在另一个页面调用。
简介
主要是想解决小程序跨页面通信的问题,我想用一种最简单,最优雅,并且让用户可以很方便的使用的小工具。
安装
将 store.js 文件放在 utils 文件夹( 可以是任意文件夹 )下即可,然后引入文件。
引入
import store from "path/store.js"
使用
推荐的使用流程是这样的,比如 b 页面需要用到 a 页面里的数据。
- 先在 a 页面引入 store 然后在 onload 方法里使用
store.addData(this, "a")
来将当前页面的执行上下文加载到 store 的数据池里。 - 在 b 页面引入 store ,然后就可以在 b 页面通过
store.a.数据名
来获取相应数据的值,也可以通过store.a.数据名 = "balabala"
来给相应的数据赋值,这里注意,这样的赋值方式是响应式的,不需要通过setData
函数来赋值就可以达到效果。(暂未实现setData
方式赋值,推荐使用直接赋值)
方法简介
-
添加页面数据
store.addData( context, name )
参数说明:
-
context
执行上下文,也就是当前页面的
this
-
name
命名当前页面,也就是在别的页面取值的时候
store.name.属性
,默认值为当前页面的路径
-
-
移除页面数据
store.removeData( name )
参数说明
-
name
希望删除的页面数据的名字
-
-
获取数据
let value = store.页面name.属性
这样既可获取数据,后台是用代理封装了数据池,从而方便用户使用
-
修改数据
store.页面name.属性 = value
这样赋值即可,后台使用的依然是封装的
setData
-
检测属性是否存在
property in store.页面name
代码
/** * @author xiaoheng * @time 2019/8/1 * @github https://github.com/xiaoheng21 * @tip 还在找工作,有机会望告知,坐标北京 */ /** * 状态管理类 * @constructor 构造函数 * @_data 内部数据,用来保存页面数据 * @addData 添加页面数据的方法 * @removeData 移除不需要的页面数据,减小内存压力 */ class Store { constructor() { this._data = {}; } /** * 向数据池里添加数据 * @param { Object<this> } context 保存当前页面的执行上下文,也就是当前页面的 this * @param { String } name 当前页面数据的名字,用于在别的页面读取数据,默认值为当前页面的路径 */ addData(context, name) { // 如果传了 name 就用传过来的,如果未传就用页面路径 let routeName = name ? name : context.route; //设置代理,用于简化操作 let proxyContext = new Proxy(context, { // 获取数据,如果数据在外层,返回外层数据 get: function(context, property) { if (property in context) { return context[property]; } else { // 如果外层找不到数据, 就在 "this.data" 里找,若有,返回数据 if (property in context.data) { return context.data[property]; } else { //若没有,报错 console.error(`${name}页面没有此属性`); } } }, // 改变数据, 封装 "this.setData", 简化操作 set: function(context, property, value) { context.setData({ [property]: value }); return true; }, // 判断数据是否存在 has: function(context, property) { return property in context.data; } }); // 将代理对象添加进数据池 this._data[routeName] = proxyContext; } /** * 从数据池里移除页面数据 * @param { String } name 需要移除的页面的名字 */ removeData(name) { if (name in this._data) { delete this._data[name]; } else { console.error(`希望删除的属性不存在`); } } } // 创建单例对象,全局共享一个数据池 const store = new Store(); // 创建代理, 私有化 _data, 简化用户操作, 提高安全性 let proxyStore = new Proxy(store, { // 若访问的属性为 add remove 函数, 直接返回函数 get: function(store, property) { if (property in store) { return store[property]; } else { // 若访问的数据为页面数据, 则返回页面代理对象 if (property in store._data) { return store._data[property]; } else { // 若没有页面信息, 报错 console.error("访问的页面数据未载入数据池"); } } } }); export default proxyStore;