详细的存储概念
State
对象
在现代浏览器中,state
对象作为 CommandRequest
的一部分被传递。对该 state
对象的任何修改都会被转换为相应的补丁操作,并应用到存储中。
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];
});
请注意,尝试访问状态在 IE11 中不受支持,并将立即抛出错误。
StoreProvider
StoreProvider 接受三个属性
renderer
:一个渲染函数,它将存储注入以访问状态并将进程传递给子小部件。stateKey
:注册表中状态的键。paths
(可选):一个函数,用于将提供程序连接到状态的部分。
失效
StoreProvider
有两种主要方法来触发失效并导致重新渲染。
- 推荐的方法是通过将
paths
属性传递给提供程序来注册path
,以确保仅在相关状态更改时才会发生失效。 - 当容器没有定义任何
path
时,它将成为一个万能方法,当存储中的任何数据更改时,它都会失效。
Process
生命周期
Process
具有一个执行生命周期,它定义了所定义行为的流程。
- 如果存在转换器,它将首先被执行以转换有效负载
before
中间件按顺序同步执行- 命令按定义的顺序执行
- 操作在每个命令(或在多个命令的情况下,在每个命令块)执行后从命令中应用
- 如果在命令期间抛出异常,则不再执行任何命令,并且当前的操作集不会被应用
after
中间件按顺序同步执行
转换器
通过使用转换器,您可以在进程命令使用有效负载之前修改它。这是一种创建接受不同有效负载的额外进程执行器的方法。
interface PricePayload {
price: number;
}
const createCommand = createCommandFactory<any, PricePayload>();
// `payload` is typed to `PricePayload`
const setNumericPriceCommand = createCommand(({ get, path, payload }) => {});
const setNumericPrice = createProcess('set-price', [setNumericPriceCommand]);
首先,创建一个转换器,将另一种类型的输入转换为 PricePayload
interface TransformerPayload {
price: string;
}
// The transformer return type must match the original `PricePayload`
const transformer = (payload: TransformerPayload): PricePayload => {
return {
price: parseInt(payload.price, 10)
};
};
现在只需使用此转换器创建进程即可。
const processExecutor = setNumericPrice(store);
const transformedProcessExecutor = setNumericPrice(store, transformer);
processExecutor({ price: 12.5 });
transformedProcessExecutor({ price: '12.50' });
进程中间件
中间件使用可选的 before
和 after
方法应用于进程周围。这允许在进程定义的行为周围执行通用、可共享的操作。
可以通过提供一个列表来定义多个中间件。中间件按列出的顺序同步调用。
之前
before
中间件块将传递一个 payload
和对 store
的引用。
middleware/beforeLogger.ts
const beforeOnly: ProcessCallback = () => ({
before(payload, store) {
console.log('before only called');
}
});
之后
after
中间件块将传递一个 error
(如果发生错误)和进程的 result
。
middleware/afterLogger.ts
const afterOnly: ProcessCallback = () => ({
after(error, result) {
console.log('after only called');
}
});
result
实现 ProcessResult
接口,以提供有关应用于存储的更改的信息,并提供对该存储的访问权限。
executor
- 允许对存储运行其他进程store
- 对存储的引用operations
- 应用的操作列表undoOperations
- 可以用来反转应用的操作的操作列表apply
- 来自存储的 apply 方法payload
- 提供的有效负载id
- 用于命名进程的 id
订阅存储更改
Store
具有一个 onChange(path, callback)
方法,它接受一个路径或路径数组,并在该状态更改时调用回调函数。
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
事件,该事件在存储更改时触发。
main.ts
store.on('invalidate', () => {
// do something when the store's state has been updated.
});