看作者讲这个知识点
https://www.bilibili.com/video/BV1rC4y187Vw?p=8
手动收集、手动触发
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>deps依赖收集</title></head><body><script>let activeEffectclass Dep {subsctibers = new Set()depend() {if (activeEffect) {this.subsctibers.add(activeEffect);}}notify() {this.subsctibers.forEach(effect => {effect()})}}function watchEffect(effect) {activeEffect = effecteffect()activeEffect = null}const dep = new Dep()watchEffect(() => {dep.depend()console.log("effect run")}) // 这里会运行dep.notify() // 这里也会运行</script></body></html>
控制台打印
手动收集、手动触发、保存值
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>deps依赖收集</title></head><body><script>let activeEffect// 此时不仅仅跟踪它的订阅者,而且保存一个值class Dep {subsctibers = new Set()constructor(value) {this.value = value}depend() {if (activeEffect) {this.subsctibers.add(activeEffect);}}notify() {this.subsctibers.forEach(effect => {effect()})}}function watchEffect(effect) {activeEffect = effecteffect()activeEffect = null}const dep = new Dep("hello")watchEffect(() => {dep.depend()console.log(dep.value)}) // 这里会运行dep.value = "changed"dep.notify() // 这里也会运行</script></body></html>
控制台打印
自动收集、自动触发
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>deps依赖收集</title></head><body><script>let activeEffect// 此时不仅仅跟踪它的订阅者,而且保存一个值class Dep {subsctibers = new Set()constructor(value) {this._value = value}set value(value) {this._value = value;// 当我们改变value时,会隐式调用notifythis.notify() // 这里也会运行}get value() {// 当我们访问value,则会隐式调用dependthis.depend()return this._value}depend() {if (activeEffect) {this.subsctibers.add(activeEffect);}}notify() {this.subsctibers.forEach(effect => {effect()})}}function watchEffect(effect) {activeEffect = effecteffect()activeEffect = null}const dep = new Dep("hello")watchEffect(() => {console.log(dep.value)}) // 这里会运行dep.value = "changed"</script></body></html>
控制台打印
自动收集、自动触发、触发前清除依赖
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>deps依赖收集</title></head><body><script src="./deps-value-autto-many.js"></script></body></html>
let activeEffectlet effectStack = []// 此时不仅仅跟踪它的订阅者,而且保存一个值class Dep {subsctibers = []constructor(value) {this._value = value}set value(value) {this._value = value;// 当我们改变value时,会隐式调用notifythis.notify() // 这里也会运行}get value() {// 当我们访问value,则会隐式调用dependthis.depend()return this._value}depend() {if (activeEffect) {this.subsctibers.push(activeEffect);this.subsctibers = Array.from(new Set(this.subsctibers))activeEffect.deps = this.subsctibers}}notify() {debugger;this.subsctibers.forEach(effect => {effect()})}}function watchEffect(fn) {const effect = createReactiveEffect(fn)return effect()}function createReactiveEffect(fn) {debugger;const effect = function reactiveEffect() {// 这里清除依赖cleanup(effect)activeEffect = effectfn()activeEffect = null}effect.deps = []return effect}function cleanup(effect) {const {deps} = effectif (deps.length) {deps.length = 0}}const msg = new Dep("hello")const ok = new Dep(true)watchEffect(() => {if (ok.value) {console.log(msg.value)} else {console.log("false branch")}}) // 这里会运行// msg.value = "changed"msg.value = "changed"console.log('-------------------')ok.value = falseconsole.log('-------------------')msg.value = 'foo'console.log('-------------------')ok.value = trueconsole.log('-------------------')msg.value = 'hello'console.log('-------------------')
控制台打印
其他
其中还有依赖嵌套问题,如何解决请看这篇文章
Vue3.0核心源码解读 | 响应式:响应式内部的实现原理是怎样的?(下)
这部分
