vue双向数据怎么实现
Vue 双向数据绑定的实现
Vue 的双向数据绑定主要通过 v-model 指令实现,结合数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式完成数据与视图的同步更新。
基础实现方式
在表单元素上使用 v-model,语法如下:
<input v-model="message">
<p>{{ message }}</p>
对应的 JavaScript 部分:
new Vue({
el: '#app',
data: {
message: ''
}
});
v-model 是 :value 和 @input 的语法糖,等价于:
<input :value="message" @input="message = $event.target.value">
自定义组件实现双向绑定
对于自定义组件,需通过 props 和 $emit 手动实现:
-
父组件模板:

<custom-input v-model="parentMessage"></custom-input> -
子组件实现:
Vue.component('custom-input', { props: ['value'], template: ` <input :value="value" @input="$emit('input', $event.target.value)" > ` });
原理:
- 父组件通过
v-model传递parentMessage到子组件的valueprop。 - 子组件输入时触发
input事件并传递新值,父组件同步更新parentMessage。
底层原理
- 数据劫持:
Vue 2.x 使用
Object.defineProperty监听数据变化:Object.defineProperty(obj, key, { get() { return val; }, set(newVal) { val = newVal; dep.notify(); // 触发更新 } });
Vue 3.x 改用 Proxy:
new Proxy(data, {
set(target, key, value) {
target[key] = value;
triggerUpdate(); // 触发更新
}
});
- 依赖收集:
- 在 getter 中收集依赖(Watcher)。
- 在 setter 中通知依赖更新视图。
修饰符扩展
v-model 支持修饰符:

.lazy:将input事件改为change事件(失焦后更新)。.number:自动将输入转为数字类型。.trim:自动去除首尾空格。
示例:
<input v-model.lazy="msg">
<input v-model.number="age">
多选框与单选按钮
-
单选按钮:
<input type="radio" v-model="picked" value="a"> -
多选框:
<input type="checkbox" v-model="checked" value="a"> -
多选列表(绑定数组):
<select v-model="selected" multiple> <option value="a">A</option> </select>
注意事项
- 避免直接修改 prop,始终通过
$emit通知父组件。 - 对于复杂对象,需确保属性是响应式的(Vue.set 或 Vue 3 的
reactive)。 - Vue 3 的
v-model默认使用modelValue作为 prop 名,可通过参数修改:<custom-input v-model:title="pageTitle"></custom-input>






