实现简易vue响应式

实现简易 Vue 响应式
要实现一个简易的 Vue 响应式系统,核心是利用 JavaScript 的 Object.defineProperty 或 ES6 的 Proxy 来劫持数据的变化,并在数据变化时触发更新。以下是两种实现方式:
使用 Object.defineProperty
function defineReactive(obj, key, val) {
// 递归处理嵌套对象
observe(val);
Object.defineProperty(obj, key, {
get() {
console.log(`get ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`set ${key}: ${newVal}`);
observe(newVal); // 处理新值为对象的情况
val = newVal;
}
}
});
}
function observe(obj) {
if (typeof obj !== 'object' || obj === null) {
return;
}
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
});
}
const data = { foo: 'foo', bar: { a: 1 } };
observe(data);
使用 Proxy
function reactive(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
return new Proxy(obj, {
get(target, key) {
console.log(`get ${key}`);
return reactive(target[key]);
},
set(target, key, val) {
console.log(`set ${key}`);
target[key] = val;
return true;
}
});
}
const data = reactive({ foo: 'foo', bar: { a: 1 } });
依赖收集与更新
为了实现类似 Vue 的依赖收集和更新,可以引入一个简单的 Dep 和 Watcher 机制:
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeEffect) {
this.subscribers.add(activeEffect);
}
}
notify() {
this.subscribers.forEach(effect => effect());
}
}
let activeEffect = null;
function watchEffect(effect) {
activeEffect = effect;
effect();
activeEffect = null;
}
function reactive(obj) {
const deps = new Map();
return new Proxy(obj, {
get(target, key) {
let dep = deps.get(key);
if (!dep) {
dep = new Dep();
deps.set(key, dep);
}
dep.depend();
return target[key];
},
set(target, key, val) {
target[key] = val;
const dep = deps.get(key);
if (dep) {
dep.notify();
}
return true;
}
});
}
const state = reactive({ count: 0 });
watchEffect(() => {
console.log(`count is: ${state.count}`);
});
以上代码实现了一个简易的 Vue 响应式系统,包括数据劫持、依赖收集和更新触发。实际 Vue 的实现会更加复杂,包括虚拟 DOM 比对、组件系统等,但核心原理与此类似。







