看作者讲这个知识点
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 activeEffect
class Dep {
subsctibers = new Set()
depend() {
if (activeEffect) {
this.subsctibers.add(activeEffect);
}
}
notify() {
this.subsctibers.forEach(effect => {
effect()
})
}
}
function watchEffect(effect) {
activeEffect = effect
effect()
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 = effect
effect()
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时,会隐式调用notify
this.notify() // 这里也会运行
}
get value() {
// 当我们访问value,则会隐式调用depend
this.depend()
return this._value
}
depend() {
if (activeEffect) {
this.subsctibers.add(activeEffect);
}
}
notify() {
this.subsctibers.forEach(effect => {
effect()
})
}
}
function watchEffect(effect) {
activeEffect = effect
effect()
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 activeEffect
let effectStack = []
// 此时不仅仅跟踪它的订阅者,而且保存一个值
class Dep {
subsctibers = []
constructor(value) {
this._value = value
}
set value(value) {
this._value = value;
// 当我们改变value时,会隐式调用notify
this.notify() // 这里也会运行
}
get value() {
// 当我们访问value,则会隐式调用depend
this.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 = effect
fn()
activeEffect = null
}
effect.deps = []
return effect
}
function cleanup(effect) {
const {
deps
} = effect
if (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 = false
console.log('-------------------')
msg.value = 'foo'
console.log('-------------------')
ok.value = true
console.log('-------------------')
msg.value = 'hello'
console.log('-------------------')
控制台打印
其他
其中还有依赖嵌套问题,如何解决请看这篇文章
Vue3.0核心源码解读 | 响应式:响应式内部的实现原理是怎样的?(下)
这部分