v-model语法糖
v-model
v-model 可以实现双向绑定,即父组件更改值子组件中的数据也会跟着更改,同理子组件中也是一样。它本质上就是一个语法糖,他编译后的结果是一个 v-bind 和 v-on
原理:通过父组件 v-bind 和子组件 props 来达到父向传子传递数据的目的,然后通过 emit 触发事件并传递数据,通知父组件值已被更改
根据以上原理就可以实现双向绑定,v-model 只不过简化这一步的操作。v-model 默认绑定的是 props.value 属性
在VUE后续版本的更新中可能会有一些差异化内容,比如:Vue2、Vue3.0~Vue3.3和Vue3.3+
Vue2
子组件:
<template>
<input v-model="data" />
</template>
<script>
export default {
name: "child",
props: ['value'],
computed: {
data: {
get() {
return this.value
},
set(newValue) {
this.$emit('input', newValue)
}
}
}
}
</script>
以上通过计算属性来实现父组件的值更新, 当然并不是非得使用计算属性,也可以使用 watch 监听或者触发事件等等。至于为什么触发“input”因为对于大多数输入类型会默认监听“input”或者“change”事件,所以这里触发的是“input”事件;对于自定义组件来说,默认监听的是“input”事件
父组件:原本的 <child :value="username" @input="username=$event" />
就可以改成 <Child v-model="username" />
Vue3.0~Vue3.3
为了更好地支持组合式 API 和一致性,Vue 3引入了 modelValue
和 @update
的语法糖,以取代先前的 value
和 @input
v-model="xxx"
== v-model="modelValue" @update:modelValue="updateModelValue"
同样的案例:
<template>
<input
class="input"
type="text"
:value="props.modelValue"
v-on:input="updateValue($event.target.value)"
/>
</template>
<script setup>
const props = defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
const updateValue = (value) => {
emit('update:modelValue', value)
}
</script>
Vue3.4
在 3.4 版本的时候也可以继续试用 modelValue
和 @update
的语法糖,但是 3.4 又引入新的方式 defineModel
// 声明 "modelValue" prop,由父组件通过 v-model 使用
const model = defineModel()
// 或者:声明带选项的 "modelValue" prop
const model = defineModel({ type: String })
// 在被修改时,触发 "update:modelValue" 事件
model.value = "hello"
// 声明 "count" prop,由父组件通过 v-model:count 使用
const count = defineModel("count")
// 或者:声明带选项的 "count" prop
const count = defineModel("count", { type: Number, default: 0 })
// 在被修改时,触发 "update:count" 事件
count.value++