事件
使用createStore或useStore创建的AutoStore对象实例后,实例提供两个事件触发器:
- 实例事件触发器:
- 状态事件触发器
Store事件
AutoStore对象实例本身就是一个事件触发器,提供了一些事件用来监听实例的生命周期、状态变化以及计算属性等事件。
class AutoStore<State extends Dict> extends EventEmitter<StoreEvents>{
}
export type StoreEvents = {
// 响应对象创建后
'load' : AutoStore<any>;
// 响应对象销毁后
'unload' : AutoStore<any>
// 当计算对象创建时
'computed:created' : ComputedObject
// 当计算函数执行成功时
'computed:done' : {id:string,path:string[],value:any,computedObject:ComputedObject}
// 当计算函数执行出错时
'computed:error' : {id:string,path:string[],error:any,computedObject:ComputedObject}
// 当计算函数被取消时
'computed:cancel' : {id:string,path:string[],reason:'timeout' | 'abort' | 'reentry' | 'error',computedObject:ComputedObject}
// 当watch对象创建时
'watch:created' : WatchObject
// 当watch对象执行成功时
'watch:done' : {value:any,watchObject:WatchObject}
// 当watch对象执行出错时
'watch:error' : {error:any,watchObject:WatchObject}
};方法
AutoStore提供了一些方法用来监听和触发事件:
| 方法 | 说明 |
|---|---|
on | 监听事件 |
onAny | 订阅所有事件 |
once | 只监听一次事件 |
off | 取消监听事件订阅 |
offAll | 取消所有订阅 |
emit | 触发事件 |
wait | 等待事件触发 |
on
订阅事件,返回一个EventListener用来取消订阅。
export type EventListener = { off:()=>void }
on<T extends keyof Events>(
type: T,
handler: EventHandler<T,Events[T]>,
prepend ?:boolean
):EventListener
on<P=any>(
type: '**',
handler: EventHandler<keyof Events,P>,
prepend ?:boolean
):EventListenertype:事件类型,可以是具体的事件名,也可以是**,表示监听所有事件。handler:事件处理函数。prepend:是否在事件订阅队列头部插入,订阅队列是一个数组,prepend为true时会在头部插入,false时在尾部插入。这样可以使得事件处理函数的执行顺序发生变化。
onAny
订阅所有事件,返回一个EventListener用来取消订阅。
onAny(handler:EventHandler<string,any>):EventHandleronAny(handler)等效于on('**',handler)
once
只订阅一次事件,事件触发后会自动取消订阅。
once<T extends keyof Events>(
type: T,
handler: EventHandler<T,Events[T]>
) :EventListeneroff
取消订阅事件。
off<T extends keyof Events>(
type: T,
handler?: EventHandler<T,Events[T]> | undefined
)offAll
取消所有订阅。
offAll()emit
触发事件。
emit<T extends keyof Events>(type:T,payload:Events[T])wait
等待事件触发。
wait<T extends keyof Events >(
filter:(type:T,payload:Events[T])=>boolean | undefined | void,
timeout?:number
):Promise<Events[T]>
wait<T extends keyof Events>(
type:T,
timeout?:number
):Promise<Events[T]>filter:过滤器,当返回true时触发,当返回undefined时触发,当返回void时不触发。timeout:超时时间,单位毫秒。
// 等待load事件触发
await store.wait('load')
// 等待computed:done事件触发
await store.wait('computed:done',2000)事件
AutoStore提供了以下事件:
load
当AutoStore对象实例创建后触发。
store.on('load',(store:AutoStore)=>{
console.log('store loaded:',store)
})unload
当调用store.destory()销毁AutoStore对象实例后触发。
store.on('unload',(store:AutoStore)=>{
console.log('store loaded:',store)
})computed:created
当计算属性对象创建时触发。
store.on('computed:created',(computedObject:ComputedObject)=>{
console.log('computedObject created:',computedObject)
})computed:done
当计算函数执行成功时触发。
store.on('computed:done',({id,path,value,computedObject}:any)=>{
console.log('computedObject done:',id,path,value,computedObject)
})computed:error
当计算函数执行出错时触发。
store.on('computed:error',({id,path,error,computedObject}:any)=>{
console.log('computedObject error:',id,path,error,computedObject)
})computed:cancel
当异步计算函数被取消时触发。
store.on('computed:cancel',({id,path,reason,computedObject}:any)=>{
console.log('computedObject cancel:',id,path,reason,computedObject)
})reason是计算被取消的原因,取值:timeout|abort|reentry|error
watch:created
当watch对象创建时触发。
store.on('watch:created',(watchObject:WatchObject)=>{
console.log('watchObject created:',watchObject)
})watch:done
当watch函数执行成功时触发。
store.on('watch:done',({value,watchObject}:any)=>{
console.log('watchObject done:',value,watchObject)
})watch:error
当watch函数执行出错时触发。
store.on('watch:error',({error,watchObject}:any)=>{
console.log('watchObject error:',error,watchObject)
})状态变更事件
AutoStore对象实例提供了一个状态变更事件触发器operates,用来监听状态的读写变化。
当读写状态时,会触发相应的事件,store.operates就是一个普通的事件触发器对象,可以通过operates的on/once/onAny/wait方法订阅事件。所以AutoStore的所有依赖收集以及事件响应均是基于store.operates实现的。
触发状态读写事件
当对状态进行读写操作时,会在operates触发名称为<状态路径>的事件。
const store = createStore({
user:{
name:'tom',
age:18
}
})例如:
- 读操作:
console.log(store.state.user.name):
触发名称为user.name的事件。相当于store.operates.emit('user.name',<operate>)。
- 写操作:
store.state.user.name='jack':
触发名称为user.name的事件。相当于store.operates.emit('user.name',<operate>)。
事件操作参数
operates触发的事件的参数是一个StateOperate对象,用来描述状态的读写操作。
type StateOperate<Value=any,Parent=any> = {
type : StateOperateType,
path : string[],
value : Value,
indexs? : number[],
oldValue? : Value,
parentPath?: string[],
parent? : Parent,
reply? : boolean
}
type BatchChangeEvent= '__batch_update__'
type StateChangeEvents = Record<string,StateOperate>
type StateOperateType = 'get' | 'set' | 'delete' // 用于对象
| 'insert' | 'update' | 'remove' // 用于数组
| 'batch' // 批量操作StateOperate对象包含以下属性:
| 属性 | 类型 | 说明 |
|---|---|---|
type | StateOperateType | 操作类型,取值get、set、delete、insert、update、remove、batch。 |
path | string[] | 状态路径。 |
value | Value | 状态值。 |
indexs | number[] | 数组操作时的索引。 |
oldValue | Value | 旧值。 |
parentPath | string[] | 父路径。 |
parent | Parent | 父对象。 |
reply | boolean | 是否回放操作。 |
type:操作类型,get表示读操作,set表示写操作,delete表示删除操作,insert表示插入操作,update表示更新操作,remove表示删除操作,batch表示批量操作。insert、update、remove用于表示数组的插入、更新、删除操作。操作时还提供indexs属性用来表示操作的索引。get、set、delete用于表示对象的读、写、删除操作。batch用于表示批量操作。get代表所有读操作
监听状态操作
要监听状态读写操作,可以通过operates的on/once/onAny/wait方法订阅事件。
const store = createStore({
user:{
name:'tom',
age:18
}
})- 监听user.name操作
store.operates.on('user.name',(operate:StateOperate)=>{...})
- 监听所有操作
store.operates.onAny((operate:StateOperate)=>{...})
- 使用通配符
支持*通配符,可以监听所有user下的操作。
store.operates.on('user.*',(operate:StateOperate)=>{...})
提示
AutoStore的所有依赖收集以及事件响应均是基于store.operates实现的,所以store.operates是一个非常重要的事件触发器对象。
markRaw
当读写状态时,会触发相应的事件,但是有时候我们并不希望触发事件,可以使用markRaw标识。
import { isRaw,markRaw } from '@autostorejs/react'
const store = createStore({
order:markRaw({
price:9.9,
count:5,
total:(order)=>order.price*order.count
})
})
isRaw(store.state.order) // true
typeof(state.order.total) // 'function'markRaw标识的对象不会触发事件,也不会创建Proxy,不具备响应式isRaw函数用来判断对象是否被markRaw标识。- 上例中的
total也不会创建计算属性,因为order对象是markRaw标识的。