proxy实现vue
使用Proxy实现Vue响应式系统
Vue 3.x 使用 Proxy 替代了 Vue 2.x 的 Object.defineProperty 来实现响应式系统。以下是核心实现方法:
创建响应式对象
function reactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
track(target, key) // 依赖收集
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
trigger(target, key) // 触发更新
return true
}
})
}
依赖收集与触发

const targetMap = new WeakMap()
function track(target, key) {
if (!activeEffect) return
let depsMap = targetMap.get(target)
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()))
}
let dep = depsMap.get(key)
if (!dep) {
depsMap.set(key, (dep = new Set()))
}
dep.add(activeEffect)
}
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const effects = depsMap.get(key)
effects && effects.forEach(effect => effect())
}
实现计算属性
function computed(getter) {
let value
let dirty = true
const effect = effectFn(getter, {
lazy: true,
scheduler() {
dirty = true
trigger(obj, 'value')
}
})
const obj = {
get value() {
if (dirty) {
value = effect()
dirty = false
}
track(obj, 'value')
return value
}
}
return obj
}
实现简易Vue实例
创建Vue实例

class Vue {
constructor(options) {
this.$options = options
this._data = options.data()
this.$el = document.querySelector(options.el)
this.proxy = new Proxy(this, {
get(target, key) {
if (key in target._data) {
return target._data[key]
}
return target[key]
},
set(target, key, value) {
if (key in target._data) {
target._data[key] = value
target.update()
return true
}
target[key] = value
return true
}
})
this.update = this.update.bind(this)
this.effect = effectFn(() => {
this.update()
})
this.update()
}
update() {
this.$el.innerHTML = this.$options.render.call(this.proxy)
}
}
使用示例
HTML部分
<div id="app"></div>
JavaScript部分
const app = new Vue({
el: '#app',
data() {
return {
count: 0
}
},
render() {
return `
<div>
<p>Count: ${this.count}</p>
<button onclick="app.count++">Increment</button>
</div>
`
}
})
关键点说明
Proxy相比Object.defineProperty的优势在于能直接代理整个对象,无需递归遍历属性。它能检测到属性的添加和删除,支持数组索引修改和length变化,还能拦截更多操作如in操作符。
实现时需要注意处理嵌套对象的响应式转换,避免重复代理。对于数组需要特殊处理,因为Proxy能直接拦截数组的各种变异方法。






