老师请问一下watch里面为什么要监听一个函数 () => props.data

来源:3-3 歌手列表固定标题实现(上)

Elevens_regret

2021-04-11

不能直接监听 props.data 吗?为什么要把 props.data 变成一个函数的返回值来进行监听?

写回答

2回答

ustbhuangyi

2021-04-11

不可以喔,其实这个问题可以简化:

import { watch, reactive } from 'vue'

const a = reactive({
 b: []
})

watch(() => a.b, (newVal) => {
 console.log(newVal)
})

a.b = [1]

这样是可以执行回调函数的,但是改成这样就不行

watch(a.b, (newVal) => {
 console.log(newVal)
})

a.b = [1]

之所以不行,是因为你在 watch 的时候就已经访问了 a.b,这个时候它收集依赖对应的 effect 是 render effect。

而前面之所以可以,是因为 a.b 的访问延时了,watch 的 source 直接就是一个函数,然后当 a.b 真正访问的时候,这个时候收集依赖就是 watch 内部创建的 effect,这个 effect 对应的函数才会去执行回调函数 cb。

这块儿可以自己去看看 watch 实现的源码,也可以参考我在拉勾的 Vue.js 3.0 源码解析课程对这块的分析。

我再给你留一个问题,你好好思考一下。

watch(a.b, (newVal) => {
 console.log(newVal)
})

a.b.push(1) 

这样会不会执行回调,为什么。

3
7
Elevens_regret
回复
ustbhuangyi
调试了一晚上,还是不是很懂,const runner = effect(getter, {...}) 将传入的getter转为响应式函数 当回调函数cb存在时会执行 runner(),也就是执行getter返回 traverse(baseGetter()),执行getter()的时候,发现有一次在createGetter中走到了track(target, "get" /* GET */, key);函数里,这次收集依赖的时候依赖栈trackStack清空了而且 shouldTrack为true,就在这次的时候收集了依赖。老师能讲解一下吗
2021-04-11
共7条回复

ustbhuangyi

2021-04-11

//img.mukewang.com/szimg/60731a6d096ed7f816120528.jpg

在 traverse 的过程中,判断如果是数组,在遍历数组的过程中,访问了 value.length,这个时候触发了依赖收集,并且当前的 activeEffect 就是 watcher 内部创建的 effect。

2
0

Vue3开发企业级音乐Web App 明星讲师带你学大厂代码

慕课网明星讲师黄轶深度讲解 Vue3.0 ,提升的不止是Vue代码能力

2223 学习 · 1002 问题

查看课程