一个基于原生小程序的 mini 轻量全局状态管理库,跨页面/组件数据共享渲染。
- 全局状态 data 支持所有 Page 和 Component。
- 类似 Vuex 的使用
- 适合原生小程序,即使后期引入,也只需增加几行代码。
- 支持 Store 模块化配置
在开始前,你可以 clone 或下载本项目,用微信开发工具打开 demo 目录来查看效果。
目前有两种引入方式:
首先你需要 npm init 在项目目录下生成 package.json 后,再进行安装。
npm init
npm install wxminishareddata -S
然后在微信小程序右上角详情中勾选 使用npm模块
。
接着选择左上角 工具-构建 npm。
这样你就可以在项目中导入了。
如果不太熟悉 npm 没关系,你可以将本项目中 lib/index.js 复制到你的项目中,并在app.js第一行
引入:
// /store/index.js中 例如
// import Store from "wxminishareddata"; 替换成
import Store from "你存放index.js的路径";
...
// /store/index.js中 例如
import Store from "wxminishareddata"; //直接引用的话 替换成import Store from "你存放index.js的路径";
import goods from "./modules/goods";
export default new Store({
modules: {
goods,
},
data: {
appName: "实例项目",
userInfo: {},
},
getters: {
getAppName: (data: { appName: string }) => {
console.log("getter执行了");
return "我的名字" + data.appName;
},
},
mutations: {
setAppName(data, val) {
data.appName = val;
},
setUserInfo(data, val) {
data.userInfo = val;
},
},
actions: {
async getUserInfo({ storeCommit }) {
setTimeout(() => {
console.log("dispatch获取用户信息");
storeCommit("setUserInfo", {
name: "张三",
age: 18,
});
}, 1500);
},
},
});
我们现在设置了两个全局状态,一个是 appName 的字符串,一个是 userInfo 的对象。同时我们还设置了一个异步请求用来请求用户信息,mutations 里设置了两个修改 data 的方法。这里和使用 Vuex 非常相似,如果你比较熟悉 Vuex,那么你将很容易上手。
接下来我们还要在 app.js 中引入,如果同时需要调用异步方法,需要导入 storeDispatch 方法。如果要修改全局的 data,请导入 storeCommit,通过 storeCommit 方法调用 mutations 达到修改 data 的目的
// app.js 中
import "./store/index";
App({
onLaunch() {},
});
以下的 api 都是可以在 Page 或者 Component 中以 this.$xxx 的形式调用的,如果要在其他地方使用,请直接从包中引用。
1.0 版本中使用的 api,主要作用是将 Store 里的数据加载到页面或者组件的 data 中,并在全局建立起 Page 或者 Component 与 Store 的对应关系,在 Store 发生改变时,取出 Page 或者 Component,直接调用 setData 触发页面更新。如下
...
onLoad(){
this.$setStoreToPage({
appName: "appName",
userInfo: "userInfo",
});
}
...
key 对应的是页面 data 里的 key,value 对应的是 Store 里的数据。
2.0 版本中生成全局状态的副作用函数,使用方法如下
this.$effect(
() => {
console.log("detail");
this.setData({
userInfo: this.$getStoreData().userInfo,
});
},
{
scheduler: (fn) => {
console.log("打印调度器,延迟1秒执行");
setTimeout(() => {
fn();
}, 1000);
},
lazy: true,
}
);
effect 函数有两个参数,第一个参数是一个回调函数,第二个函数是一个 options 对象,可传入 scheduler,用于自己控制 effect 函数的执行。
options 属性 | 类型 | 描述 |
---|---|---|
scheduler | Function | 入参 fn 是当前 effect 的回调函数 |
lazy | Boolean | 是否延迟到页面的 onShow 执行,默认是 true,建议使用默认值,如果在 app.js 中使用,建议设置为 false |
用于触发 Store 里的 mutations,以便更新 Store 的 data。第一个参数是"模块名/mutations 名",主模块的模块名默认为"",调用直接调用"mutations 名",其他模块的模块名可使用 name 定义,如果未定义则使用在主模块 modules 里的 key。除使用 getStoreData 获取全局状态是通过对象调用,其他 api 的调用都适用这个。第二个参数可以传递任意参数。
this.$storeCommit("setUserInfo", {
name: "李四",
age: 20,
});
获取 Store 的 data 引用,建议只使用这个 api 获取 store,而不要直接更改 store,如果要更改,请使用 storeCommit 更改。
this.setData({
userInfo2: this.$getStoreData().userInfo,
goodList: this.$getStoreData().goods.goodList,
});
可以在 Store 里定义 getter,getter 会缓存计算的结果,如果依赖的 store 没有变化,只会返回之前计算的结果。
console.log(this.$storeGetters("getAppName"));
调用 store 的 actions 异步函数
最近也是在写原生微信小程序中使用 storage 共享状态时,维护和更新不同页面需要太多的精力去做,所以花了一下午写了这个非常粗糙的方案。因为在看《Vue.js 设计与实现》,所以边看边按照书上实现了个在插件中响应式,主要困难是 Vue 的响应式都是单文件的,所以它不用担心页面销毁后的副作用函数还存在的问题,但在这里,响应式是全局存在的,并不会因为页面或组件的销毁而销毁,所以我在页面销毁前清除了当前页面所有 effect。
大家有使用上的问题或者想法可以发邮件给我 联系我 [email protected] 最后欢迎来我的 github 点个小星星
[2024.6.24] : 修复 currentpage 获取错误,导致 effect lazy 执行无效。
[2024.5.20] : 修复若干 bug,优化 effect 执行时机,只在当前页面执行,其他页面缓存到 onShow 中执行。
[2024.5.18] : 引入响应式,支持 getter 缓存,模块化配置
[2024.5.13] : 主要利用发布订阅,粗暴实现。