vue双向实现数据
Vue 双向数据绑定的实现
Vue 的双向数据绑定主要通过 v-model 指令实现,它结合了属性绑定和事件监听,使表单输入和应用状态保持同步。
使用 v-model 实现双向绑定
v-model 是语法糖,自动处理 value 属性和 input 事件。适用于大多数表单元素,如 <input>、<textarea> 和 <select>。
<input v-model="message" placeholder="Edit me">
<p>Message is: {{ message }}</p>
data() {
return {
message: ''
}
}
自定义组件实现双向绑定
在自定义组件中,可以通过 model 选项和 $emit 实现双向绑定。
<custom-input v-model="searchText"></custom-input>
Vue.component('custom-input', {
props: ['value'],
model: {
prop: 'value',
event: 'input'
},
template: `
<input
:value="value"
@input="$emit('input', $event.target.value)"
>
`
})
使用 .sync 修饰符
.sync 修饰符是另一种实现双向绑定的方式,适用于需要同步多个 prop 的情况。
<text-document :title.sync="doc.title"></text-document>
Vue.component('text-document', {
props: ['title'],
template: `
<input
:value="title"
@input="$emit('update:title', $event.target.value)"
>
`
})
底层原理:数据劫持与发布订阅
Vue 通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)劫持数据变化,结合发布订阅模式实现响应式。
// 简化的数据劫持示例
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
return val
},
set(newVal) {
if (newVal === val) return
val = newVal
// 触发更新
}
})
}
对比 Vue 2 和 Vue 3 的实现
Vue 2 使用 Object.defineProperty 实现数据劫持,需要递归遍历对象并为每个属性设置 getter/setter。
Vue 3 改用 Proxy 代理整个对象,能检测到新增/删除属性,性能更好。
// Vue 3 使用 Proxy
const handler = {
get(target, key) {
return Reflect.get(target, key)
},
set(target, key, value) {
Reflect.set(target, key, value)
// 触发更新
return true
}
}
const observed = new Proxy(data, handler)
注意事项
- 对象新增属性需要使用
Vue.set(Vue 2)或直接赋值(Vue 3) - 数组变异方法需要特殊处理(Vue 2)
- 深层嵌套对象需要递归观察(Vue 2)
v-model默认使用valueprop 和input事件,可通过model选项修改







