Vue3系列(十四)之详解v-model

371 阅读1分钟

v-model实际上就是一个语法糖,等同于propsemit的操作,只是vue帮我们做了这部分操作

vue2中的v-model

使用input事件

在vue2中封装组件时,我们使用v-model去给组件绑定数据,实际上组件内部等同于接收了一个属性为valueprop,然后在我们需要改变v-model绑定的值时,我们需要通过emit一个input事件去将新的值返回,从而达到数据绑定的效果。

示例

// src/components/Input.vue
<template>
  <div>
    <input type="text" :value="showValue" @input="handleInput($event)">
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      default: ''
    },
  },
  data() {
    return {
      showValue: ''
    }
  },
  methods: {
    handleInput($event) {
      this.showValue = $event.target.value
      this.$emit('input', $event.target.value)
    }
  }
}
</script>

页面中使用这个组件

<template>
  <Input v-model="inputVal"></Input>
  <button @click="handleClick">查看最新的inputVal</button>
</template>

<script>
import Input from '@/components/Input.vue';
export default {
  name: 'HelloWorld',
  data() {
    return {
      inputVal: ''
    }
  },
  methods: {
    handleClick() {
      console.log(this.inputVal)
    }
  }
}
</script>

image.png

vue3中的v-model

在vue3中,v-model已经支持传递多个,且有了以下的改变:

  • prop: 使用 modelValue
  • emit: 使用 updata:modelValue
  • v-bind的 .sync修饰符已经移除
  • 支持自定义修饰符 Modifiers

单个v-model

示例

// /src/components/Input.vue
<template>
  <div>
    <input :value="inputValue" @input="($event) => handleInput($event)">
  </div>
</template>

<script setup>
import { ref } from 'vue';

const inputValue = ref('')

const propData = defineProps({
  modelValue: String
})
 
const emit = defineEmits(['update:modelValue'])

const handleInput = ($event) => {
  inputValue.value = $event.target.value
  emit('update:modelValue',$event.target.value)
}

</script>

页面中使用这个组件

<template>
  <InputVue v-model="inputVal"></InputVue>
  <button @click="handleClick">查看最新的inputVal</button>
</template>

<script setup>
import InputVue from './components/Input.vue'
import { ref } from 'vue';

const inputVal = ref('')

const handleClick = () => {
  console.log(inputVal.value);
}
</script>

image.png

多个v-model

组件上的每一个 v-model 都会同步不同的 prop,因此我们可以创建多个 v-model 双向绑定

语法:

用法propemit
v-modlemodleValueupdate:modleValue
v-modle:titletitleupdate:title

示例

<template>
  <div>
    <input :value="inputValue" @input="($event) => handleInput($event)">
    <p>
      title: {{ title }}
      <button @click="handleChangeTitle">更改title</button>
    </p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const inputValue = ref('')

const propData = defineProps({
  modelValue: String,
  title: String
})
 
const emit = defineEmits(['update:modelValue', 'update:title'])

const handleInput = ($event) => {
  inputValue.value = $event.target.value
  emit('update:modelValue',$event.target.value)
}

const handleChangeTitle = () => {
  emit('update:title', 'title被组件更新了')
}

</script>

页面中使用

<template>
  <InputVue v-model="inputVal" v-model:title='title'></InputVue>
  <button @click="handleClick">查看最新的inputVal</button>
</template>

<script setup>
import InputVue from './components/Input.vue'
import { ref } from 'vue';
import { RouterLink, RouterView } from 'vue-router'

const inputVal = ref('')
const title = ref('title')

const handleClick = () => {
  console.log(inputVal.value);
}
</script>

image.png

image.png