微信小程序全局状态管理库(wxMiniStore)

一个基于原生小程序的mini全局状态管理库,跨页面/组件渲染。

  • 全局状态state支持所有Page和Component,状态完全同步,并提供api,自动diff状态并更新。

  • 周期监听pageLisener能监听所有页面的onLoad,onShow等周期事件。

  • 全局事件methods,全局可用的方法。

  • 适合原生小程序,可以随时引入,不影响原有的业务,拓展性强。

#基本使用

1.npm引入

npm init
npm install wxministore -S

注意:
npm导入包需在微信小程序右上角详情中勾选 使用npm模块。
接着选择左上角 工具-构建 npm。

//app.js中
import Store from 'wxministore';
//或者 const Store = require('wxministore');
App({
})

2.创建实例

let store = new Store({
  state: {
    msg: '这是一个全局状态',
    user: {
      name: "李四"
    }
  }
})
console.log(store.getState().msg); //这是一个全局状态(推荐使用)
console.log(store.$state.msg); //这是一个全局状态 (不推荐)
App({
})

3.挂载注册

App({
  onLaunch: function () {
 
  },
  store: store
})

4.页面中使用

 <view>{{$state.user.name}}{{$state.msg}}</view> 

如果在template文件中使用,需在属性data中引用$state

 <!-- 这是一个template -->
  <template name="t1">
    <view>{{$state.msg}}</view>
  </template>
 
<!-- 这是引用位置 -->
  <template is="t1" data="{{$state,arg1,arg2}}" />
<!--   相当于<template is="t1" data="{{$state:$state,arg1:arg1,arg2:arg2}}" /> -->

在版本1.2.1+建议使用App.Page和 App.Component创建页面和组件,当然也不是必须

// 没问题
Page({
  //...
})
 
// 更好
App.Page({
  //...
})

如果使用时,页面空白,说明你没有在App创建前new Store。
5.修改状态
使用app.store.setState进行更新状态

const app = getApp()
App.Page({
  data: {
 
  },
  onLoad: function () {
    //所有wxml中的$state.msg会同步更新
    app.store.setState({
       msg: "我被修改了,呜呜..."
    });
  }
});

修改状态注意事项

// 错误的示范 视图不会更新
let { user } = app.store.$state;
user.name = '张三';
app.store.setState({
  user
}); 
 
//正确的示范
let { user } = app.store.getState();
user.name = '张三';
app.store.setState({
  user
});

获取全局状态需使用app.store.getState()。
6.周期监听 pageLisener
Store会自动在相应周期优先执行pageLisnner然后再执行原页面周期内事件。

// store中
let store = new Store({
    //状态
    state: {
        //...
    },
    //方法
    methods: {
        //...
    },
    //页面监听
    pageLisener: {
        onLoad(options){
            console.log('我在' + this.route, '参数为', options);
        }
    }
})

支持其他周期事件 [‘onLoad’, ‘onShow’, ‘onReady’, ‘onHide’, ‘onUnload’, ‘onPullDownRefresh’, ‘onReachBottom’, ‘onShareAppMessage’, ‘onPageScroll’, ‘onTabItemTap’]
7.全局方法 methods
新增methods,全局可使用。 适用于各个wxml中的交互事件(bindtap等),可以封装一些常用的交互事件,如页面跳转。

let store = new Store({
  //状态
  state: {
      msg: '这是一个全局状态'
  },
  //方法
  methods: {
      goAnyWhere(e){
          wx.navigateTo({
              url: e.currentTarget.dataset.url
          })
      }
    }
  }
})

在wxml中使用全局方法

<view bindtap="goAnyWhere" data-url="/index/index">
  首页
</view>

非交互型事件(即非bindxx)的公用方法,建议不写入Store中。写入App中更好。
8.局部状态模式

在项目的组件和页面越来越多且复用率越来越高时,全局 s t a t e 的 利 用 率 就 很 低 , 这 时 候 就 出 现 了 一 种 情 况 , 页 面 中 的 组 件 和 页 面 达 到 百 千 量 级 , 每 个 内 部 都 有 一 个 state的利用率就很低,这时候就出现了一种情况,页面中的组件和页面达到百千量级,每个内部都有一个 statestate,而用到它的可能就只有1个或几个。就会引起各种性能问题。比如更新 s t a t e 十 分 缓 慢 , 且 低 效 。 这 时 候 你 需 要 将 state十分缓慢,且低效。 这时候你需要将 statestate调整为部分组件和页面可用,而不是所有。
1.开启局部模式

let store = new Store({
  //。
  state: {
    msg: '这是一个全局状态'
  },
  openPart: true
})

openPart 字段表示是否开启局部模式,默认值为false。当我们想规定只有某些页面和组件使用$state时,就需开启此模式,设置为true。

2.设置范围

在需要使用 s t a t e 的 组 件 中 , 加 入 u s e S t o r e : t r u e , 表 示 当 前 页 面 或 组 件 可 用 state的组件中,加入useStore: true,表示当前页面或组件可用 stateuseStore:truestate。

// a.js
App.Page({
  useStore: true,
  onLoad(){
    console.log(this.data.$state) // { msg: '这是一个全局状态' }
    console.log(getApp().store.getState()) // { msg: '这是一个全局状态' }
  }
})
 
// b.js
App.Page({
  onLoad(){
    console.log(this.data.$state) // undefined
    console.log(getApp().store.getState()) // { msg: '这是一个全局状态' }
  }
})

a页面设置了Store可用,所以可以通过this.data.$state获取。 b页面没有设置,所以为undefined,但两个页面均可通过store.getState()读取全局状态。

<--! a页面有效 -->
<view>{{$state.msg}}</view>
 
<--! b页面无效 -->
<view>{{$state.msg}}</view>

3.注意事项

openPart一旦开启,所有没有设置useStore的页面和组件将不能在wxml中使用 s t a t e 。 组 件 或 页 面 . j s 中 , 我 们 建 议 使 用 g e t A p p ( ) . s t o r e . g e t S t a t e ( ) 去 获 取 全 局 状 态 , 因 为 他 没 有 限 制 。 仅 在 w x m l 中 需 要 用 到 state。 组件或页面.js中,我们建议使用getApp().store.getState()去获取全局状态,因为他没有限制。 仅在wxml中需要用到 state.js使getApp().store.getState()wxmlstate的页面和组件中开启useStore。

页面中useProp属性 1.2.3+

useProp 用于控制当前页面/组件,使用哪些状态,不传则所有状态均可在当前页面中使用。

观察以下代码及注释:

// App.js
let store = new Store({
  state: {
    s1: 's1状态',
    s2: 's2状态'
  }
})
 
// A页面中
App.Page({
  useProp: ['s1'], //指定使用s1
  onLoad(){
    console.log(this.data.$state) // { s1: 's1状态' }
    console.log(getApp().store.getState()) // { s1: 's1状态', s2: 's2状态' }
  }
})
 
// B页面中
App.Page({
  useProp: ['s2'], //指定使用s2
  onLoad(){
    console.log(this.data.$state) // { s2: 's2状态' }
    console.log(getApp().store.getState()) // { s1: 's1状态', s2: 's2状态' }
  }
})
 
// C页面中
App.Page({
  onLoad(){
    console.log(this.data.$state) // { s1: 's1状态', s2: 's2状态' }
    console.log(getApp().store.getState()) // { s1: 's1状态', s2: 's2状态' }
  }
})

useProp是控制当前组件/页面使用哪些状态,而useStore是控制哪些组件/页面可使用state这个功能,两者可以同时作用。如:

// App.js中
let store = new Store({
  state: {
    s1: 's1状态',
    s2: 's2状态'
  },
  openPart: true
})
 
// A页面中
App.Page({
  useStore: true,
  useProp: ['s1'], //指定使用s1
  onLoad(){
    console.log(this.data.$state) // { s1: 's1状态' }
    console.log(getApp().store.getState()) // { s1: 's1状态', s2: 's2状态' }
  }
})
 
// B页面中
App.Page({
  useProp: ['s1'], //指定使用s1 但没设置useStore,所以无效
  onLoad(){
    console.log(this.data.$state) // undefined
    console.log(getApp().store.getState()) // { s1: 's1状态', s2: 's2状态' }
  }
})

其他 1.2.9+

实例化Store时,提供debug字段,用于开启/关闭框架内部console日志。 默认值为true,即开启状态。如不需要,则设置false即可。

new Store({
debug: false // 关闭内部日志的输出。
})

non-writable解决方案 1.2.1+

在小程序中使用插件时,会报错提示:

// [non-writable] modification of global variable “Page” is not
allowed when using plugins at app.json. // 在app.json中使用插件时,不允许修改全局变量
Page

原因是store源码重写了Page、Component方法。

1、开启防改写 在你的store配置中,加入 nonWritable: true。

let store = new Store({
nonWritable: true
})

2、创建页面与组件调整 将你所有页面与组件创建方法改为App.Page(…) 和 App.Component(…)。

//页面.js
App.Page({
  data: {
 
  },
  onLoad: function () {
  }
});
 
//组件.js
App.Component({
  data: {
 
  }
});

以上就解决了此问题。
api

这里列举了所有涉及到Store的属性与方法。
new Store(options: Object) *已更新

该函数使用new关键字返回一个Store类型的实例。 参数options,为配置参数,
options.state 为初始全局状态。
options.methods 为全局方法。
options.openPart 状态局部模式。
options.pageLisener 周期监听。
options.nonWritable 是否重写Page,Componenet。
Store.prototype.setState(Object data, Function callback)

用于修改全局状态,用法与微信小程序的 Page.prototype.setData完全一致。 提示:页面中应避免使用this.setData({KaTeX parse error: Expected 'EOF', got '}' at position 11: state: ...}̲)去操作当前页面下的state。如有相关需求,请使用页面其他状态存储。
store.$state : Object

该对象为实例. s t a t e , 返 回 的 是 全 局 状 态 , 应 避 免 直 接 操 作 修 改 它 。 s t o r e . state, 返回的是全局状态,应避免直接操作修改它。 store. statestore.r : Object

该对象为所有页面或组件的实例。
store.getState() : Object 1.2.6+

该api返回的是全局状态的拷贝。
总结及建议

考虑到后期的app.js内store不直观,可以把整套store单独写入一个js中,通过require引入。如:

// mystore.js中
const Store = require('../util/store.js');
module.exports = new Store({
  state: {},
  methods: {}
})
//---------------------------
// app.js中
let store = require('store/mystore.js')
App({
  store
})

根据npm官网中wxMiniStore包编辑

在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值