欢迎来到258分享网,纯净的网络源码分享基地!

258资源分享网

全部作品
全部作品
网站源码
微信源码
素材特效
源码插件
视频教程
建站学院
热门搜索: 织梦  农业种植  农业  安全设置  官方
258资源分享 > 建站学院 > 微信开发 > 手把手系列,100行代码搞定微信小程序全局状态同步

推荐下载

HTML5响应式自适应网咯设计

2020-05-12   浏览:738

高端HTML5响应式企业通用网

2020-05-06   浏览:518

html5响应式外贸网站英文版

2020-05-08   浏览:505

HTML5自适应律师工作室类网

2020-04-04   浏览:502

HTML5影视传媒文化公司类网

2020-05-12   浏览:496

手把手系列,100行代码搞定微信小程序全局状态同步

发布时间:2020-09-30  

最近接了一个小程序项目,对于以前只写过一个小工具的我而言,是时候考察一波小程序的基本功了(认真脸)。

手把手系列,100行代码搞定微信小程序全局状态同步

上手先了解了各路大神撸小程序的方式,前有基于vue语法的mpvue ,专职生成小程序;又有基于react的京东团队的taro 在后,一语多端,支持react语法生成小程序、H5、react-native......;还有官方wepy,仿vue语法,官方支持更稳定......都芥末:ox:的吗? 赶紧每个都学习了一下。

然鹅——

手把手系列,100行代码搞定微信小程序全局状态同步

!!翻开issue页,似乎都有几十到上百条的open isuue未解决,同时还有一些诡异的bug夹杂其中,好怕怕。遂放弃......逃

于是手撸原生框架,于是遇到了原生框架中一个最大的问题,全局状态同步管理 /(ㄒoㄒ)/~~。

小程序框架提供了许多开箱即用的组件,大大提高我们的开发效率。但是作为一个不能直接引用js npm包的语法 (支持的模式很繁琐) ,同时小程序本身也没有提供类似redux、vuex的全局的状态管理工具,这简直违反了mvc(mvvm)党的一贯作风。

于是想到了手写一个简单的全局状态管理库,从各方面考察似乎可行,毕竟是一个接近vue的框架。

心路历程如上。。。。。。还是不废话了,上主菜 (可直接翻到文末查看代码完整版) 。

小程序官方提供且推荐的demo中是把全局数据放在app实例上——示例 ,咋一看似乎很接近我们的全局状态管理需求,但这只是一个数据存储方式,完全没法做到响应式状态。

想想我们常见的需求,在个人中心页点击“去登录”,跳转到登录页,测试一番骚操作,好不容易登录成功了,返回个人中心,依旧是一个大大的“去登陆”按钮在嘲讽着他/她,于是测试打了你一顿并让你回去加班。

手把手系列,100行代码搞定微信小程序全局状态同步

这时候你完全可以在onShow中使用 this.setData 刷新每一次页面展开......前提是你不怕繁琐,同时愿意消耗更多的性能(sex power)。

所以开始手写,第一步,在项目中生成一个 /store/sotre.js 文件。

再放两个轮子中常用的方法

const _toString = Object.prototype.toString function isFunction(obj) { return typeof obj === 'function' || false } function isObject(obj) { return _toString.call(obj) === '[object Object]' || false } 复制代码
 
createStore

全局状态管理理索当然需要一个全局的状态存储,同时考虑使用react-redux的connect模式做绑定:

let _state = null function connect(mapStateToData, mapMethodTopPage) { ... } /** * 创建store对象 * * @param { Object } store * @returns { Object } _Store */ function createStore(state) { if (_state) { console.warn( 'there are multiple store active. This might lead to unexpected results.' ) } _state = Object.assign({}, state) // 这里返回_Store的原因是因为想通过app实例直接获取 // const { connect, setState, createStore } = getApp().Store return _Store } const _Store = { connect, setState, createStore } module.exports = _Store 复制代码  
connect

现在的打算是将_state作为内部存储,以免暴露出去被直接操作,无法做到响应式(单一状态树只读原则)。接下来的重点当然是作为绑定数据和修改数据相互响应了,先来connect:

let _state = null let _subjects = [] // 用来存储页面实例对象 let _observers = [] // 用来存储状态响应器 /** * 仿写react-redux的connect简单工厂 * * @param { Function } mapStateToData * @param { Function } mapMethodTopPage * @returns { Function } pageConnect */ function connect(mapStateToData, mapMethodTopPage) { // mapStateToData接收state参数,且必须返回一个绑定对象,key会被绑定到page实例的data中 const dataMap = mapStateToData ? mapStateToData(_state) : {} // mapMethodTopPage接收setState和state参数,且必须返回一个绑定对象,key会被绑定到page实例上 const methodMap = mapMethodTopPage ? mapMethodTopPage(setState, _state) : {} return function(pageObject) { // 接收page对象 // 遍历绑定data for (let dataKey in dataMap) { if (pageObject.data) { if (pageObject.data[dataKey]) { console.warn( `page class had data ${dataKey}, connect map will cover this prop.` ) } pageObject.data[dataKey] = dataMap[dataKey] } else { pageObject.data = { [dataKey]: dataMap[dataKey] } } } // 遍历绑定method for (let methodKey in methodMap) { pageObject[methodKey] = methodMap[methodKey] } // 存储onLoad、onUnload周期函数,以便对其做改造 const onLoad = pageObject.onLoad const onUnload = pageObject.onUnload pageObject.onLoad = function() { // 存储page实例和事件响应器,两者保持同步,一个实例对应一个响应器 if (!~_subjects.indexOf(this)) { // 首次load需要修改data this.setData(mapStateToData ? mapStateToData(_state) : {}) _subjects.push(this) _observers.push(() => { // mapStateToData生成新的mapData,并使用this.setData更新page状态 this.setData(mapStateToData ? mapStateToData(_state) : {}) }) } // 触发原有生命周期函数 onLoad && onLoad.call(this) } pageObject.onUnload = function() { // 注销响应器 const index = _subjects.indexOf(this) if (!~index) { _subjects.splice(index, 1) _observers.splice(index, 1) } // 触发原有生命周期函数 onUnload && onUnload.call(this) } return pageObject } } 复制代码  
setState

本文标签

:备案管家服务帮您把复杂流程变简单,解决您在进行网站备案过程中遇到的效率低下和成功率不高的问题。个人300/2个域名,企业500/5个域名,qq1650004.