Skip to content

批量更新

一般情况下,更新多个状态时会触发多个set事件。在React场景中,为了优化渲染,我们可能希望一次性更新多个状态,只触发一次渲染。

AutoStore内置批量更新机制,以下介绍其工作机制,以及如何使用。

工作机制

ts
const sore = new AutoStore({
    name:"Fisher"
    age:18
})
  1. 首先当执行store.state.name='Wang'store.state.age=20时,会触发两次set事件。
tsx
{
    "type":"set",
    "path":["name"],
    "value":"Wang"
}
{
    "type":"set",
    "path":["age"],
    "value":20
}
  1. 正常情况下,set事件会触发React组件的重新渲染,但是如果我们希望一次性更新多个状态,只触发一次渲染,此时使用batchUpdate方法。
tsx
store.batchUpdate(state=>{
    store.state.name='Wang'
    store.state.age=20
})
  • batchUpdate方法会设置store._batchingtrue,然后执行store.state.name='Wang'store.state.age=20,q这导致触发两次set事件。

  • 但是由于store._batching=true,所以两次set事件会被拦截收集到store._batchOperates中。

  • 执行state的更新操作后,再将store.batching设置为false

  • 重点来了:此时做了两个操作:

    • store._batchOperates中的所有set事件设置reply=true代表这是一批量更新操作后的事件回放。这样可以保证正常订阅者可以收到set事件,而批量更新优化时,可以通过判定reply=true来忽略此事件。
    ts
    {
        "type":"set",
        "path":["name"],
        "value":"Wang",
        "reply":true
    }
    {
        "type":"set",
        "path":["age"],
        "value":20,
        "reply":true
    }
    • 然后将store._batchOperates中的所有set事件合并一个batch类型的事件,如下
    ts
    {
        "type":"batch",
        "path":["__batch_update__"],
        "value":[
            {
                "type":"set",
                "path":["name"],
                "value":"Wang",
                "reply":true
            },
            {
                "type":"set",
                "path":["age"],
                "value":20,
                "reply":true
            }
        ]
    }
  1. 按照以上原理,当执行批量更新操作时:
ts
store.batchUpdate(state=>{
    store.state.name='Wang'
    store.state.age=20
})

就会触发三个事件,如下:

ts
    // 回放事件
    {
        "type":"set",
        "path":["name"],
        "value":"Wang",
        "reply":true
    }
    // 回放事件
    {
        "type":"set",
        "path":["age"],
        "value":20,
        "reply":true
    }
    // 合并批量事件
    {
        "type":"batch",
        "path":["__batch_update__"],
        "value":[
            {
                "type":"set",
                "path":["name"],
                "value":"Wang",
                "reply":true
            },
            {
                "type":"set",
                "path":["age"],
                "value":20,
                "reply":true
            }
        ]
    }

优化渲染时就只需要:忽略批量更新后的回放事件响应批量更新后的合并后的batch事件,如下:

tsx
    store.watch((operate)=>{
        if(operate.reply) return  // 是批量更新后的回放事件,忽略
        if(operate.type==='batch'){ 
            // 此时触发一次渲染
        }
    })