test: update multi-store testing

This commit is contained in:
dntzhang 2019-10-22 09:22:13 +08:00
parent 25f52d6d20
commit 89146d7005
7 changed files with 68 additions and 359 deletions

View File

@ -1,247 +0,0 @@
## omix
> 小程序全局状态管理,极小却精巧,对小程序入侵性几乎为零
TypeScript 版本的例子可以点击这里 [omix-ts](https://github.com/Tencent/omi/tree/master/packages/omix-ts)
## 3分钟精通
### API
* `create(store, option)` 创建页面, store 可跨页面共享
* `create(option)` 创建组件
* `this.store.data``this.data` 全局 store 和 data页面和页面所有组件可以拿到 操作 data 会自动更新视图
## 实战
定义 store:
```js
export default {
data: {
logs: []
}
}
```
定义页面:
```js
import create from '../../utils/create'
import util from '../../utils/util'
import store from '../../store'
create(store, {
//声明依赖
use: ['logs'], //也支持复制的格式,比如 ['list[0].name']
onLoad: function () {
this.store.data.logs = (wx.getStorageSync('logs') || []).map(log => {
return util.formatTime(new Date(log))
})
setTimeout(() => {
this.data.logs[0] = 'Changed!'
}, 1000)
setTimeout(() => {
this.store.data.logs.push(Math.random(), Math.random())
}, 2000)
setTimeout(() => {
this.data.logs.splice(this.store.data.logs.length - 1, 1)
}, 3000)
}
})
```
```html
<view class="container log-list">
<block wx:for="{{logs}}" wx:for-item="log">
<text class="log-item">{{index + 1}}. {{log}}</text>
</block>
<view>
<test-store></test-store>
</view>
</view>
```
可以看到里面使用 test-store 组件, 看下组件源码:
```js
import create from '../../utils/create'
create({
})
```
```html
<view class="ctn">
<view>
<text>Log Length: {{logs.length}}</text>
</view>
</view>
```
## 其他配置
修改 store.js 的 debug 字段用来打开和关闭 log 调试:
```js
export default {
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
logs: []
},
debug: true, //我是开关
updateAll: true //当为 true 时,无脑全部更新,组件或页面不需要声明 use
}
```
默认是打开的,`store.data` 的所以变动都会出现在开发者工具 log 面板,如下图所示:
![](../../assets/omix.png)
## 其他
这里需要注意,改变数组的 length 不会触发视图更新,需要使用 size 方法:
```js
this.oData.arr.size(2) //会触发视图更新
this.oData.arr.length = 2 //不会触发视图更新
this.oData.arr.push(111) //会触发视图更新
//每个数组的方法都有对应的 pureXXX 方法
this.oData.arr.purePush(111) //不会触发视图更新
```
###  函数属性
```js
use: [
'motto',
'userInfo',
'hasUserInfo',
'canIUse',
{
reverseMotto:[
['motto'],
motto => motto.split('').reverse().join('')
]
}
],
```
函数属性定义在页面或者组件的 use 里,如上面的 `reverseMotto` 它可以直接绑定在 wxml 里motto 更新会自动更新 reverseMotto 的值。
### store 变化监听
```js
const handler = function (evt) {
console.log(evt)
}
//监听,允许绑定多个
store.onChange(handler)
//移除监听
store.offChange(handler)
```
### 复杂 store 拆分到多文件
这里举个例子:
store-a.js:
```js
export default {
data: {
a: {
name: 'omix'
}
}
}
```
store-b.js:
```js
export default {
data: {
b: {
name: 'I Love Omix',
age: 18
}
}
}
```
store.js:
```js
import a from './a.js'
import b from './b.js'
export default {
data: {
a: a.data.a,
b: b.data.b
}
}
```
数据绑定:
```html
<view>
<text>{{a.name}}</text>
<text>{{b.name}}-{{b.age}}</text>
</view>
```
数据使用:
```js
import create from '../../utils/create'
import store from '../../store/store'
create(store, {
//声明依赖
use: ['a.name', 'b'],
onLoad: function () {
setTimeout(() => {
store.data.a.name = 'omi'
}, 2000)
}
})
```
扩展公共方法用于多个视图,比如 store-methods.js:
```js
import store from './store.js'
export function changeAge(age){
store.data.b.age = age
}
```
如果仅一个视图使用可以把该方法写在视图的 js 里便可以,不用提取到单独的文件。
## Q & A
* 比如我一个弹窗组件可能在很多页面使用也可能在同一个页面使用多次如果使用store来作为组件间通信的话怎么应用可以实现组件是纯组件而不跟业务相关呢?
纯组件不用不用 create 创建,且该组件内使用 [triggerEvent](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html) 通知父组件改变 store.data 或者调用 store 的方法与外界通讯。
## License
MIT © Tencent

View File

@ -1,71 +1,15 @@
import create from '../../utils/create'
import store from '../../store'
//获取应用实例
const app = getApp()
import store from '../../store/store'
create(store, {
use: [
'motto',
'userInfo',
'hasUserInfo',
'canIUse',
{
reverseMotto:[
['motto'],
motto => motto.split('').reverse().join('')
]
}
],
//事件处理函数
bindViewTap: function () {
wx.navigateTo({
url: '../logs/logs'
})
},
use: ['a.name', 'b'],
onLoad: function () {
if (app.globalData.userInfo) {
this.store.data.userInfo = app.globalData.userInfo
this.store.data.hasUserInfo = true
} else if (this.data.canIUse) {
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
app.userInfoReadyCallback = res => {
this.store.data.userInfo = res.userInfo
this.store.data.hasUserInfo = true
}
} else {
// 在没有 open-type=getUserInfo 版本的兼容处理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.store.data.userInfo = res.userInfo
this.store.data.hasUserInfo = true
}
})
}
setTimeout(() => {
this.store.data.logs.push('abc')
this.store.data.motto = '123456'
setTimeout(_ => {
store.a.changeName()
}, 1000)
setTimeout(() => {
this.store.data.motto = 'abcdefg'
setTimeout(_ => {
store.b.changeAge()
}, 2000)
const handler = function (evt) {
console.log(evt)
}
store.onChange(handler)
store.offChange(handler)
},
getUserInfo: function (e) {
this.store.data.userInfo = e.detail.userInfo
this.store.data.hasUserInfo = true
}
})

View File

@ -1,14 +1,4 @@
<!--index.wxml-->
<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}}-{{reverseMotto}}</text>
</view>
<test-store />
<view>
<text>{{a.name}}</text>
<text>{{b.name}}-{{b.age}}</text>
</view>

View File

@ -0,0 +1,7 @@
export const data = {
name: 'omix'
}
export function changeName(){
data.name = 'Omix'
}

View File

@ -0,0 +1,8 @@
export const data = {
name: 'dntzhang',
age: 18
}
export function changeAge(){
data.age++
}

View File

@ -0,0 +1,13 @@
import { data as dataA, changeName } from 'store-a.js'
import { data as dataB, changeAge } from 'store-b.js'
const store = {
data:{
a: dataA,
b: dataB
},
a: { changeName },
b: { changeAge }
}
export default store

View File

@ -158,42 +158,45 @@ store.offChange(handler)
store-a.js:
```js
export default {
data: {
a: {
name: 'omix'
}
}
export const data = {
name: 'omix'
}
export function changeName(){
data.name = 'Omix'
}
```
store-b.js:
```js
export default {
data: {
b: {
name: 'I Love Omix',
age: 18
}
}
export const data = {
name: 'dntzhang',
age: 18
}
export function changeAge(){
data.age++
}
```
store.js:
```js
import a from './a.js'
import b from './b.js'
import { data as dataA, changeName } from 'store-a.js'
import { data as dataB, changeAge } from 'store-b.js'
export default {
data: {
a: a.data.a,
b: b.data.b
}
const store = {
data:{
a: dataA,
b: dataB
},
a: { changeName },
b: { changeAge }
}
```
export default store
```
数据绑定:
@ -210,31 +213,22 @@ export default {
import create from '../../utils/create'
import store from '../../store/store'
create(store, {
//声明依赖
use: ['a.name', 'b'],
onLoad: function () {
setTimeout(() => {
store.data.a.name = 'omi'
}, 2000)
setTimeout(_ => {
store.a.changeName()
}, 1000)
setTimeout(_ => {
store.b.changeAge()
}, 2000)
}
})
```
扩展公共方法用于多个视图,比如 store-methods.js:
```js
import store from './store.js'
export function changeAge(age){
store.data.b.age = age
}
```
如果仅一个视图使用可以把该方法写在视图的 js 里便可以,不用提取到单独的文件。
完整的案例可以 [点击这里](https://github.com/Tencent/omi/tree/master/packages/omix-multi-store)
## Q & A