《Vue进阶教程》第二十九课:立即执行的回调
往期内容:
《Vue进阶教程》第十八课:避免死循环
《Vue进阶教程》第十九课:computed初步实现
《Vue进阶教程》第二十课:lazy懒执行
《Vue进阶教程》第二十一课:支持缓存
《Vue进阶教程》第二十二课:自定义更新(调度器)
《Vue进阶教程》第二十三课:渲染计算属性的结果
《Vue进阶教程》第二十四课:优化
《Vue进阶教程》第二十五课:watch基本概念
《Vue进阶教程》第二十六课:实现侦听函数
《Vue进阶教程》第二十七课:实现侦听对象
《Vue进阶教程》第二十八课:实现新旧值
默认情况下, watch中的回调是不执行的. 但是可以通过传入参数让其立即执行
第一次立即执行回调时, 拿到的旧值是undefined
基本使用
<!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>Document</title>
<script src="./vue.js"></script>
</head>
<body>
<script>
const { reactive, watch } = Vue
const state = reactive({ name: 'xiaoming', address: { city: '武汉' } })
watch(
() => state.name,
(newValue, oldValue) => {
console.log('设置immediate选项会立即执行回调')
console.log(newValue, oldValue)
},
{ immediate: true }
)
setTimeout(() => {
state.name = 'xiaopang'
}, 1000)
</script>
</body>
</html>
具体实现
立即执行的函数和更新时执行的函数本质上是没有区别的
因此, 我们可以将scheduler
封装起来
function watch(source, cb, options = {}) {
let getter
if (typeof source == 'function') {
getter = source
} else {
getter = () => traverse(source)
}
let oldValue, newValue
const job = () => {
newValue = _effect.run()
cb(newValue, oldValue)
oldValue = newValue
}
const _effect = effect(getter, {
lazy: true,
scheduler: job,
})
if (options.immediate) {
job()
} else {
oldValue = _effect.run()
}
}