深度代理
vue
<template>
<div ref="wrapper"></div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { effect, reactive } from '../source/reactivity'
const wrapper = ref(null)
const state = reactive({
name: '小李大人',
age: 18,
address: {
city: '杭州',
province: '浙江'
}
})
onMounted(() => {
effect(() => {
wrapper.value.innerHTML = `姓名:${state.name},年龄:${state.age},城市:${state.address.city},省份:${state.address.province}`
})
setTimeout(() => {
state.address.city = '宁波'
}, 1000)
})
</script>页面效果 
1s后:

可以看到,state.address.city 的值发生了变化,但是页面并没有重新渲染, 这是因为 state.address 并没有被代理,所以它的属性并没有被依赖收集。
js
import { isObject } from '../utils'
import { track, trigger } from './reactiveEffect'
const IS_REACTIVE_KEY = '__v_isReactive'
/** 缓存代理过的对象 */
const reactiveMap = new WeakMap()
const mutableHandlers = {
get(target, key, receiver) {
// 访问对象是否被代理过的属性
if (key === IS_REACTIVE_KEY) return true
const value = Reflect.get(target, key, receiver)
// 依赖收集
track(target, key)
if (isObject(value)) {
return reactive(value)
}
return value
},
set(target, key, value, receiver) {
const oldValue = target[key]
const result = Reflect.set(target, key, value, receiver)
if (oldValue !== value) {
// 触发更新
trigger(target, key, value, oldValue)
}
return result
}
}
/** 实现一个reactive函数,用于创建响应式对象 */
export function reactive(obj) {
// 首先判断参数是不是对象
if (!isObject(obj)) {
return obj
}
// 判断对象是否已经被代理过
if (obj[IS_REACTIVE_KEY]) {
return obj
}
// 如果代理过,则直接返回代理过的对象
if (reactiveMap.has(obj)) {
return reactiveMap.get(obj)
}
const proxy = new Proxy(obj, mutableHandlers)
// 缓存代理过的对象
reactiveMap.set(obj, proxy)
return proxy
}在reactive 函数中,我们在get中判断获取的值是不是一个对象,如果是一个对象那么就递归的调用reactive函数,将其变成响应式对象。
修复完成后的效果如下:
页面效果 
1s后:
