vue3 reactive 使用心得

119 阅读1分钟
背景

一个列表通过分页接口获取第一页数据并渲染

使用过程
  • 使用一(错误用法):
const {reactive, effect} = VueCore
// const {reactive, ref, effect} = VueReactivity
let list = reactive([{
    name: 1
}, {
    name: 2
}])
effect(() => {
    let str = ''
    list.forEach(data => {
        str = str + '==' + data.name
    })
    document.getElementById('1').innerText = str
})
setTimeout(() => {
    // 如果这里是第一页,需要重置list
    const addList = [{
        name: 3
    }, {
        name: 4
    }]
    // list = addList // 不渲染
    list = reactive(addList) // 不渲染
}, 1000)

发现用list = addList 和list = reactive(addList) 都不渲染,直接list = addList 不渲染能理解,毕竟list已经不是响应式对象了,但是 list = reactive(addList) 也不渲染,修改代码

  • 使用二:
let list = reactive({
    value: [...] //修改部分
})
setTimeout(() => {
    // ...
    list.value =  // 修改部分
}, 1000)

这样在数组外面包一层,正常渲染了。继续改代码

  • 使用三:
let list = reactive( [...] // 修改部分
)
setTimeout(() => {
    const addList = [...]
    list.length = 0 // 修改部分
    // 或者
    // list.splice(0,list.length);
    list.push(...addList)  // 修改部分
}, 1000)

去掉数组外面的包裹层,拿到数据后先把length赋值为0,再push ,正常渲染

分析原因

通过源码得知触发更新的副作用函数和原始数据的引用之间是建立的关联的,正是有了这个关联,才能在数据变化时找到对应的副作用函数执行触发更新,关系图

企业微信截图_1675908056808.png 所以我们对数据的所有操作,都是在不动这个关系的情况下才能正常运行

结论
-    list = addList这样很显然,已经不是响应式对象
-    list = reactive(addList)这样虽然是响应式对象,但是addList和原始数据之间不是同一个引用。破坏了关联关系
-    在数据外面包裹一层,通过.value操作或者不包裹,对list进行数组的操作,都没有改变关联关系

关联关系建立过程