你可以零入侵式实现小程序的网络状态管理吗

来源:未知 浏览 205次 时间 2021-06-16 04:03

哈喽今天我们聊聊小程序的状态管理~(有这玩意吗)

我们要实现什么

很简单实现一个全局响应式的globalData百度SEO优化实现一个全局响应式的globalData任何地方修改=>全局对应视图数据自动更新。

你可以零侵入式实现小程序的全局状态管理吗

为啥要实现

写过小程序的都知道状态管理一直是小程序的一大痛点。

由于小程序官方没有一个全局状态管理机制想要使用全局变量只能在app.js里调用App()创建一个应用程序实例然后添加globalData属性。但是这个globalData并不是响应式的也就是说在某个页面中修改了其某个值(如果初始化注入到data中)无法完成视图更新更别说全局页面和组件实例的更新了。

你可以零侵入式实现小程序的全局状态管理吗

我们以westore为例这是鹅厂出的一款覆盖状态管理、跨页通讯等功能的解决方案主要流程是通过自维护一个store(类似vuex)组件每当页面或组件初始化时注入并收集页面依赖在合适的时候手动update实现全局数据更新。提供的api也很简洁但是如果使用的话需要对项目原有代码做一些侵入式的改变。比如说一:创建页面或组件时只能通过该框架的api完成。二:每次改变全局对象时都要显式的调用this.update()以更新视图。

其他一些方案也都是类似的做法。但我实在不想重构原项目(其实就是懒)于是走上了造轮子的不归路。

准备工作

正式开始前我们先理一下思路。我们希望实现

将globalData响应式化。

收集每个页面和组件data和globalData中对应的属性和更新视图的方法。

修改globalData时通知所有收集的页面和组件更新视图。

其中会涉及到发布订阅模式这块不太记得的可以看看我之前的文章哟。

Talk is cheap. Show me the code.

说了这么多也该动动手了。

首先我们定义一个调度中心Observer用来收集全局页面组件的实例依赖以便有数据更新时去通知更新。 但这里有个问题网站优化以便有数据更新时去通知更新。 但这里有个问题收集整个页面组件实例未免太浪费内存且影响初始化渲染(下面的obj)如何优化呢?

// 1.Observer.js export default class Observer { constructor() { this.subscribers = {}; } add (key, obj) { // 添加依赖 这里存放的obj应该具有哪些东东? if (!this.subscribers[key]) this.subscribers[key] = []; this.subscribers[key].push(obj); } delete () { // 删除依赖 // this.subscribers... } notify(key, value) { // 通知更新 this.subscribers[key].forEach(item => { if (item.update && typeof item.update === 'function') item.update(key, value); }); } } Observer.globalDataObserver = new Observer(); // 利用静态属性创建实例(相当于全局唯一变量) 复制代码

相信很多同学想到了其实我们只需要收集到页面组件中data和更新方法(setData)就够了想到这里不妨自定义一个Watcher类(上面的obj)每次页面组件初始化时new Watcher()并传入需要的数据和方法那我们先完成初始化注入的部分。

// 2.patcherWatcher.js // 相当于mixin了Page和Component的一些生命周期方法 import Watcher from './Watcher'; function noop() {} const prePage = Page; Page = function() { const obj = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; const _onLoad = obj.onLoad || noop; const _onUnload = obj.onUnload || noop; obj.onLoad = function () { const updateMethod = this.setState || this.setData; // setState可以认为是diff后的setData const data = obj.data || {}; // 页面初始化添加watcher 传入方法时别忘了绑定this指向 this._watcher = this._watcher || new Watcher(data, updateMethod.bind(this)); return _onLoad.apply(this, arguments); }; obj.onUnload = function () { // 页面销毁时移除watcher this._watcher.removeObserver(); return _onUnload.apply(this, arguments); }; return prePage(obj); }; // 。。。下面省略了Component的写法基本上和Page差不多 复制代码

接着根据我们的计划完成Watcher的部分。这里会对传入的data做层过滤我们只需要和globalData对应的属性(reactiveData)并在初始化时注入Observer。

标签: 组件页面我们更新