vue手动实现双向绑定
Vue 手动实现双向绑定的方法
双向绑定的核心是数据变化时更新视图,视图变化时更新数据。Vue 通过 v-model 指令实现,手动实现需结合数据劫持和事件监听。
使用 Object.defineProperty 实现数据劫持
通过 Object.defineProperty 拦截对象的属性读写,触发更新逻辑。

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
return val;
},
set(newVal) {
if (newVal !== val) {
val = newVal;
updateView(); // 数据变化时更新视图
}
},
});
}
function observe(obj) {
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
});
}
视图到数据的绑定
通过事件监听(如 input 事件)将视图变化同步到数据。
const input = document.getElementById('input');
input.addEventListener('input', function(e) {
data.message = e.target.value; // 视图变化时更新数据
});
数据到视图的绑定
定义一个更新视图的函数,将数据渲染到 DOM。

function updateView() {
document.getElementById('output').innerText = data.message;
}
完整示例
<input id="input" type="text" />
<p id="output"></p>
<script>
const data = { message: '' };
observe(data);
const input = document.getElementById('input');
input.addEventListener('input', function(e) {
data.message = e.target.value;
});
function updateView() {
document.getElementById('output').innerText = data.message;
}
function observe(obj) {
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
});
}
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
return val;
},
set(newVal) {
if (newVal !== val) {
val = newVal;
updateView();
}
},
});
}
</script>
使用 Proxy 替代 Object.defineProperty
Proxy 可以更灵活地拦截对象操作,支持数组和嵌套对象。
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
updateView();
return true;
},
});
}
const data = reactive({ message: '' });
实现一个简易的 v-model
结合数据劫持和事件监听,封装一个类似 v-model 的功能。
function bindInput(inputElement, data, key) {
inputElement.value = data[key];
inputElement.addEventListener('input', (e) => {
data[key] = e.target.value;
});
// 数据变化时更新输入框
const proxy = reactive(data);
proxy[key] = data[key];
}






