前言
我们在开发小程序时难免遇到需要应用全局状态的地方,但是第三方的库大都是直接封装的Page和Component,代码入侵性有点高,使用时原来的诸多页面都需要改动;因此自己开发一个简单的状态管理功能来使用,使用效果还不错。实现了低侵入性,无需修改原来代码,只需按需添加状态即可。
状态管理库源码
//全局状态共享
class Store{
constructor(options){
this.state=options.state;//全局状态
this.dep={};//状态依赖
}
//添加依赖
addDep(page,state){
for(let key in state){
this.state[key]=state[key]
if(!this.dep[key]){
this.dep[key]={
pages:[],
pageIds:{}//不重复添加
}
}
let pageId=page.__route__;
if(!this.dep[key].pageIds[pageId]){
this.dep[key].pageIds[page.__route__]=1;
this.dep[key].pages.push(page)
}
}
// console.log(option)
page.setData(state);
}
//移除卸载的页面
removeDep(page,state){
for(let key in state){
if(this.dep[key]){
this.dep[key].pages=this.dep[key].pages.filter(item=>{
if(item.__route__==page.__route__){
this.dep[key].pageIds[page.__route__]=null;
}
return item.__route__!=page.__route__;
})
}
}
}
//更新状态
setStore(state){
for(let key in state){
this.state[key]=state[key];
// console.log(key,this.state[key])
this.dep[key].pages.forEach(page=>{
page.setData(state)
// console.log(page)
})
}
}
}
//初始化全局状态
export function initStore(app,store){
app.$store=new Store(store);
}
//page或者component调用
export function useStore(page,state){
let store=getApp().$store;
if(!state){//不定义自己要使用的状态,会应用全部状态
state=store.state;
}
if(!page.$store){//状态初始化每个界面只调用一次,后续调用不生效
page.$store=store;
// console.log(page)
//卸载页面时在页面中移除当前页面
page.onUnload=function(){
store.removeDep(page,state)
}
store.addDep(page,state)
}
}
//在不应用全局状态的界面提供更新全局状态方法
export function setStore(state){
let store=getApp().$store;
store.setStore(state);
}
复制代码
使用
全局状态初始化,这一步首先需要我们在现在app.js对状态管理库进行初始化。即调用initStore
。
import {initStore} from './utils/Store'
App({
onLanuch(){
initStore(this,{
state:{
message:'全局状态'
}
})
}
})
复制代码
在需要使用全局状态的地方使用useStore()
或者setStore()
这两个api去修改和获取全局状态。
我们可以直接在onload中直接使用useStore
,useStore
做了两件事:
- 把当前的页面或者组件添加到状态依赖中;
- 为当前页面或者组件添加全局状态管理对象
store
的引用$store
,方面我们使用。
进而我们可以直接使用this.$soter
这种语法去调用我们提供的setStore
去更新状态。
import {useStore} from './utils/Store'
Page({
updateState(){
//调用过useStore应用全局状态的页面可以直接使用this.$store更新,无需引入setStore
this.$store.setStore({message:'新状态111'})
}
onLoad(){
//useStore如果不传第二个参数,会应用所有的全局状态到当前的页面或者组件,传了第二个参数则只会在当前页面
//或者组件上添加指定的状态
useStore(this,{
message:'新状态'
})
}
})
复制代码
需要注意的是useStore如果不传第二个参数,会应用所有的全局状态到当前的页面或者组件,传了第二个参数则只会在当前页面或者组件上添加指定的状态。
此外,如果我们不需要把当前页面或者组件添加到状态依赖中,只需要去更新状态的话,那么我们直接在页面中引入setStore
函数,使用它来更新状态即可。
import {setStore} from './utils/Store'
Page({
updateState(){
//直接使用setStore更新状态
setStore({message:'新状态111'})
}
})
复制代码
最后
以上就是自己做的一个微信小程序的简易全局状态管理库,给出了全部源码和使用方法,本人使用起来感觉还不错,如果对你有帮助还望不吝点赞和关注,本人会持续更新一些技术文章。如果不足,还望不吝指正。