美文网首页
vue3 watch reactive对象的理解

vue3 watch reactive对象的理解

作者: maomizone | 来源:发表于2022-03-18 16:43 被阅读0次
const state = reactive({
  foo: 1,
  bar: 2,
  person: {
    name: 'andy',
    a: {
      b: 1
    }
  }
})
  • state是reactive定义的响应式对象,它是Proxy实例对象,Proxy可以对target对象上面的所有属性的增删改查等都能拦截
  • state.person也是Proxy实例对象,isReactive(state.person)为true,那么它也能直接被watch
watch(state.person, () => {
  console.log('state.person变化了');
})
watch(() => state.person, () => {
  console.log('state.person变化了');
}, { deep: true })

// 如果是 state.person里面的属性改变了,那么watch(state.person, cb)这个cb会执行,因为reactive定义的响应式对象是强制开启deep:true
// watch( () => state.person, cb) 要加上配置项{ deep: true },cb才会执行
state.person.name = 'hehe'
state.person.a = {b: 666}
state.person.a.b = 999
// 如果把 state.person重新赋值,那么就需要watch(() => state.person, cb)这个cb才会执行
state.person = {name: 'ddd'}

state.person里面的属性改变了

  • watch(state.person, cb)这个cb会执行,因为reactive定义的响应式对象是强制开启deep:true
  • watch( () => state.person, cb) 要加上配置项{ deep: true },cb才会执行

state.person重新赋值

  • watch(() => state.person, cb)这个cb才会执行

1. 当给state 的属性person重新赋值的时候,state.person从proxy对象变为普通对象

2. 直接watch(state.person, cb)是捕捉不到的,因为state.person已经不是reactive的了,这个watch已经失效

这和vue2中的watch不一样,因为看过vue2实现watch的源码,就是你监听state.person,即使重新赋值也是可以侦听到的,原理就是在Object.defineProperty的setter方法里面通知dep去update订阅者(watcher),而watcher就是去执行回调函数。

toRef toRefs

  • toRef创建一个ref对象,value值存储的是指向源数据的引用地址,读取它的value值其实是访问源数据
const refPerson = toRef(state, 'person')
// const { person: refPerson } = toRefs(state) // 另外一种写法
console.log(refPerson); // ObjectRefImpl
console.log(refPerson.value === state.person); // true

// 等同于watch( () => state.person, cb)
watch(refPerson, () => {
  console.log('state.person变化了');
}, {deep:true})

// 等同于watch(state.person, cb)
watch(refPerson.value, () => {
  console.log('state.person变化了');
})

vue3 watch源码部分截图

  • source即watch方法传入的第一个参,我们这儿分别是state.person 和 () => state.person
  • watch Api中的watch有个变量getter,有个runner变量(用来生成副作用),代码会自动执行一下runner(),其实就是执行effect(),也就是执行getter(),执行过程势必会走到source里面的proxy的get里面,这样子这个runner副作用会被收集起来,如果deep=true,还会被traverse包装一下,对其所有子属性递归监听
  • 设置deep为true后,state.person及其子属性变化后,就会通知到runner副作用,runner就会再次执行啦


    1.png
2.png

相关文章

网友评论

      本文标题:vue3 watch reactive对象的理解

      本文链接:https://www.haomeiwen.com/subject/fftwdrtx.html