1. 如果没有响应式,我们怎么进行更新
const obj = {
name: 'zhangsan'
}
function fn() {
document.body.innerHTML = obj.name
}
fn() // 这里界面上是 zhangsan
obj.name = 'lisi' // 当我们改变名字时,界面上仍然是 zhangsan
fn() // 只有当我们重新执行 fn() 时,才会更新界面
可以看到,如果没有响应式的加持,我们更新完数据,页面是不会发生变化的,当我们重新执行函数,也就是重新获取最新的值来获取更新,所以所谓的响应式就是把这个更新的过程给自动化了,当数据变化时,自动地去更新用到此数据的地方
2. 实现一个简单的响应式
const data = {
text: '响应式'
}
function effect() {
document.body.innerHTML = obj.text
}
// 定义一个 “桶”
const bucket = new Set();
const obj = new Proxy(data, {
get(target, key) {
// 当读数据时,把 effect 收集起来
bucket.add(effect);
return target[key]
},
set(target, key, newVal) {
// 值更新了,重新执行一下依赖它的程序。
target[key] = newVal;
// 把收集到的 effect 函数重新执行,以达到更新
bucket.forEach(fn => fn())
return true
}
})
effect(); // 触发读取, getter 监听到,收集起来
setTimeout(() => {
obj.text = '新' // 触发 setter,重新执行 effect 更新
}, 1000);
这里的 effect 其实代表着用到数据的地方,可能对应着我们的视图,也就是类比与之前 Vue 2 里面的 watcher,再 get 里手机 effect,当变化时触发 set 通知收集到的 effect 重新执行,这样就实现了简单的响应式
上面的实现只是简单的实现,我们并没有做到 key 和 effect 一一对应,并且我们的只能做这个指定的 effect 。我们接下来需要
我们定义一个变量来存储 effect ,
let activeEffect = null;
// 传如用到数据的函数,这样就做到了匿名函数实现收集
function effect(fn) {
activeEffect = fn;
fn()
}
const bucket = new WeakMap()
const obj = new Proxy(data, {
get(target, key) {
// 如果没有 effect 也就是没有用到该属性的地方,直接就 return
if (!activeEffect) return target[key];
// 从 “桶” 中取得依赖 map,一个 key --> effects 的 Map 结构
let depsMap = bucket.get(target);
if (!depsMap) {
bucket.set(target, (depsMap = new Map()))
}
// 到这里,就已经建立(存在)一个关系,类似
// 一个 weakMap,key:target , value: Map, 这个 Map: key:对象的每一个属性 ,value:是一个set里面存有多个 effect
// 然后根据 key 从 depsMap 中拿到 deps 是一个 set
let deps = depsMap.get(key);
if (!deps) {
depsMap.set(key, (deps = new Set()));
}
// 向deps 中添加 effect
deps.add(activeEffect)
return target[key]
},
set(target, key, newVal) {
// 值更新了,重新执行一下依赖它的程序。
target[key] = newVal;
// 拿到对象下面存的所有key--> effects map
const depsMap = bucket.get(target);
if (!depsMap) return;
// 拿到key 对应的 effects
const effects = depsMap.get(key)
effects && effects.forEach(fn => fn());
return true
}
})
这样就实现了一个相对完善的响应式。
实在编不下去了
这个记录,是看 《Vue 设计与实现》做的笔记相当于,这本书真的很好,对深入了解 vue 很有帮助,强烈推荐,看我的这篇记录不如去看原书,配合源码,哈哈哈。