响应式
const user = reactive({name:'xx'})
const handleUser = (newName) => {
user.name = newName
}
- 构建一个响应式数据对象user, 在模版里面展示user.name, 点击更换名字,模版自动更新user.name为新名字,数据的改变同步视图的更新。
视图自动更新的完整流程
- 渲染阶段:Vue 组件渲染时,响应式数据被访问。这时
Proxy 的 get 拦截器会触发依赖收集,将当前的渲染函数(即 effect)与被访问的数据属性关联起来。
- 数据修改:当用户交互或其他操作导致响应式数据发生变化时,
Proxy 的 set 拦截器会捕捉这个修改操作,并调用 trigger 函数。
- 触发更新:
trigger 函数通知所有依赖于修改后的数据属性的 effect 函数重新执行,这些 effect 函数通常会重新渲染视图。
- 视图更新:由于
effect 函数重新执行,组件视图将被重新渲染,展示最新的数据状态。
proxy代理对象做数据劫持
const baseHandlers = {
get: function(target, key) {
const res = Reflect.get(target, key)
track(target, "get", key);
return res;
},
set: function(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
// 在触发 set 的时候进行触发依赖
trigger(target, "set", key)
return result
}
}
// 创建一个Proxy对象对数据进行劫持,进行依赖收集的track,和修改时候的统一响应式触发trigger;
const proxy = new Proxy(
target,
baseHandlers
)
proxyMap.set(target, proxy)
return proxy
新组装的effect函数
- 用来包裹真正的副作用函数fn, 然后执行一遍fn; 进行依赖收集
function effect(fn, options) {
const effectFn = () => {
activeEffect = effectFn;
return fn()
}
effectFn();
return effectFn;
}
track的实现:依赖收集
const map = new Map()
function track(target, key, effect) {
const depsMap = map.get(target)
if(!depsMap) {
const depsMap = new Map();
map.set(target, depsMap)
}
let dep = depsMap.get(key);
if(!dep) {
dep = new Set();
}
if(!dep.has(activeEffect) && activeEffect) {
deps.add(activeEffect)
}
depsMap.set(key, deps)
}
- 依赖收集,就收集进去target[key]对应的副作用函数; 副作用函数和业务如何结合起来,依赖收集的时候为什么要activeEffect;用activeEffect来关联两边副作用的执行;
trigger的实现- 触发更新
function trigger(target, type, key) {
const desMap = map.get(target)
if(!desMap) return
const desp = desMap.get(key)
if(!deps) return
deps.forEach(effectFn => {
effectFn()
})
}