【Proxy 】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" v-model="content" />
<input type="text" v-model="title" />
<input type="text" v-model="title" />
<h4 v-bind="title">这里也会发生更新</h4>
<script>
function View() {
let proxy = new Proxy(
{},
{
set(obj, property, value) {
console.log(value);
document
.querySelectorAll(`[v-model="${property}"]`)
.forEach((el) => {
el.value = value;
});
document
.querySelectorAll(`[v-bind="${property}"]`)
.forEach((el) => {
el.innerHTML = value;
});
},
get(obj, property) {},
}
);
this.init = function () {
const els = document.querySelectorAll("[v-model]");
els.forEach((el) => {
el.addEventListener("keyup", () => {
proxy[el.getAttribute("v-model")] = el.value;
});
});
};
}
new View().init();
</script>
</body>
</html>
详细解释一下这个数据流程:
- 初始化阶段:
this.init = function () {
const els = document.querySelectorAll("[v-model]"); // 获取所有带 v-model 的输入框
els.forEach((el) => {
el.addEventListener("keyup", () => {
// 当输入时,给 proxy 对象设置属性
proxy[el.getAttribute("v-model")] = el.value;
});
});
};
- 当用户输入时:
- 假设用户在
v-model="title"的输入框输入 "hello" proxy["title"] = "hello"被执行- 这会触发 Proxy 的 set 陷阱
- set 陷阱被触发:
set(obj, property, value) { // property 是 "title", value 是 "hello"
// 更新所有 v-model="title" 的输入框
document.querySelectorAll(`[v-model="${property}"]`)
.forEach((el) => {
el.value = value;
});
// 更新所有 v-bind="title" 的元素
document.querySelectorAll(`[v-bind="${property}"]`)
.forEach((el) => {
el.innerHTML = value;
});
}
这就实现了:
- 一个输入框变化
- 所有相关输入框和绑定元素都更新
- 这就是 Vue 双向绑定的简单实现原理

浙公网安备 33010602011771号