自己实现一个简易微信小程序全局状态管理库

前言

我们在开发小程序时难免遇到需要应用全局状态的地方,但是第三方的库大都是直接封装的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中直接使用useStoreuseStore做了两件事:

  • 把当前的页面或者组件添加到状态依赖中;
  • 为当前页面或者组件添加全局状态管理对象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'})
  }
})
复制代码

最后

以上就是自己做的一个微信小程序的简易全局状态管理库,给出了全部源码和使用方法,本人使用起来感觉还不错,如果对你有帮助还望不吝点赞和关注,本人会持续更新一些技术文章。如果不足,还望不吝指正。

猜你喜欢

转载自juejin.im/post/7033579676165472293