小程序开发原生框架是足够好的,唯一缺点就是没有一个全局状态管理和跨页通讯的工具。
针对微信小程序的状态管理,接触使用github上如下的插件库
- Westore —— 1KB javascript覆盖状态管理、跨页通讯、插件开发和云数据库开发
- OMIX 2.0 —— westore 的进化版
Westore
文件结构
项目结构只是加了在utils里面的diff.js、create.js以及store.js。里面的diff是核心的库文件,create主要是页面注册用的,而store就是管理全局的数据中心。
API
Westore API 只有六个, 大道至简:
- create(store, option) 创建页面
- create(option) 创建组件
- this.update([data]) 更新页面或组件,其中 data 为可选,data 的格式和 setData 一致
- store.update([data]) 更新页面或组件,在非页面非组件的 js 文件中使用
- store.method(path, fn) 更新或扩展函数属性,注意这里不能直接赋值的方式修改函数属性,需要使用 store.method
- store.onChange = fn 监听 store data 的变化回调,一般可在里面写一些上报或监控数据变化的其他公共逻辑
纯组件使用小程序自带的 Component,或使用 create({ pure: true })。create的方式可以使用 update 方法,Component 方式不行。
创建页面
import store from '../../store'
import create from '../../utils/create'
const app = getApp()
create(store, {
//只是用来给 westore 生成依赖 path 局部更新
data: {
motto: null,
userInfo: null,
hasUserInfo: null,
canIUse: null,
b: { arr: [ ] },
firstName: null,
lastName: null,
fullName: null,
pureProp: null
},
onLoad: function () {
if (app.globalData.userInfo) {
this.store.data.userInfo = app.globalData.userInfo
this.store.data.hasUserInfo = true
this.update()
} else if (this.data.canIUse) {
app.userInfoReadyCallback = res => {
this.store.data.userInfo = res.userInfo
this.store.data.hasUserInfo = true
this.update()
}
} else {
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.store.data.userInfo = res.userInfo
this.store.data.hasUserInfo = true
this.update()
}
})
}
}
})
创建 Page 只需传入两个参数,store 从根节点注入,所有子组件都能通过 this.store 访问。
绑定数据
<view class="container">
<view class="userinfo">
<button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
<view>{{fullName}}</view>
<hello></hello>
</view>
和以前的写法没有差别,直接把 store.data 作为绑定数据源。
data 的函数属性也可以直接绑定,但别忘了要在页面上声明相应的函数属性依赖。
更新页面
this.store.data.any_prop_you_want_to_change = 'any_thing_you_want_change_to'
this.update()
创建组件
import create from '../../utils/create'
create({
ready: function () {
//you can use this.store here
},
methods: {
//you can use this.store here
}
})
和创建 Page 不一样的是,创建组件只需传入一个参数,不需要传入 store,因为已经从根节点注入了。
更新组件
this.store.data.any_prop_you_want_to_change = 'any_thing_you_want_change_to'
this.update()
跨页面同步数据
使用 westore 你不用关心跨页数据同步,你只需要专注 this.store.data 便可,修改完在任意地方调用 update 便可:
this.update()
setData 和 update 对比
拿官方模板示例的 log 页面作为例子:
this.setData({
logs: (wx.getStorageSync('logs') || []).map(log => {
return util.formatTime(new Date(log))
})
}, () => {
console.log('setData完成了')
})
使用 westore 后:
this.store.data.logs = (wx.getStorageSync('logs') || []).map(log => {
return util.formatTime(new Date(log))
})
this.update().then(diff => {
console.log('setData完成了')
console.log('更新内容为', diff)
})
看似一条语句变成了两条语句,但是 this.update 调用的 setData 是 diff 后的,所以传递的数据更少。