Skip to content

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

子组件:

vue
<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"

同样的案例:

vue
<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

javascript
// 声明 "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++