Store 概念详解
State
对象
在现代浏览器中,state
对象是作为 CommandRequest
的一部分传入的。对 state
对象的任何修改都将转换为相应的 operation,然后应用到 store 上。
import { createCommandFactory } from '@dojo/framework/stores/process';
import { State } from './interfaces';
import { remove, replace } from '@dojo/framework/stores/state/operations';
const createCommand = createCommandFactory<State>();
const addUser = createCommand<User>(({ payload, state }) => {
const currentUsers = state.users.list || [];
state.users.list = [...currentUsers, payload];
});
注意,IE 11 不支持访问 state,如果尝试访问将立即抛出错误。
StoreProvider
StoreProvider 接收三个属性
renderer
: 一个渲染函数,已将 store 注入其中,能访问状态并向子部件传入 process。stateKey
: 注册状态时使用的 key 值。paths
(可选): 将此 provider 连接到状态的某一局部上。
失效
StoreProvider
有两种方法触发失效并促使重新渲染。
- 推荐的方式是,通过向 provider 传入
paths
属性来注册path
,以确保只有相关状态变化时才会失效。 - 另一种是较笼统的方式,当没有为 provider 定义
path
时,store 中的 任何 数据变化都会引起失效。
Process
生命周期
Process
有一个执行生命周期,它定义了所定义行为的流程。
- 如果存在转换器,则首先执行转换器来转换 payload 对象
- 按顺序同步执行
before
中间件 - 按顺序执行定义的 command
- 在执行完每个 command (如果是多个 command 则是一块 command)之后,应用命令返回的 operation
- 如果在执行命令期间抛出了异常,则不会再执行后续命令,并且也不会应用当前的 operation
- 按顺序同步执行
after
中间件
Process 中间件
使用可选的 before
和 after
方法在 process 的前后应用中间件。这允许在 process 所定义行为的前和后加入通用的、可共享的操作。
也可以在列表中定义多个中间件。会根据中间件在列表中的顺序同步调用。
Before
before
中间件块能获取传入的 payload
和 store
的引用。
middleware/beforeLogger.ts
const beforeOnly: ProcessCallback = () => ({
before(payload, store) {
console.log('before only called');
}
});
After
after
中间件块能获取传入的 error
(如果发生了错误的话)和 process 的 result
。
middleware/afterLogger.ts
const afterOnly: ProcessCallback = () => ({
after(error, result) {
console.log('after only called');
}
});
result
实现了 ProcessResult
接口,以提供有关应用到 store 上的变更信息和提供对 store 的访问。
executor
- 允许在 store 上运行其他 processstore
- store 引用operations
- 一组应用的 operationundoOperations
- 一组 operation,用来撤销所应用的 operationapply
- store 上的 apply 方法payload
- 提供的 payloadid
- 用于命名 process 的 id
订阅 store 的变化
Store
有一个 onChange(path, callback)
方法,该方法接收一个或一组 path,并在状态变更时调用回调函数。
main.ts
const store = new Store<State>();
const { path } = store;
store.onChange(path('auth', 'token'), () => {
console.log('new login');
});
store.onChange([path('users', 'current'), path('users', 'list')], () => {
// Make sure the current user is in the user list
});
Store
中还有一个 invalidate
事件,store 变化时就触发该事件。
main.ts
store.on('invalidate', () => {
// do something when the store's state has been updated.
});