vue3 v-model

150 阅读2分钟

此篇文章介绍的用法,vue的版本号>=3.4

作用

    1. 如果用在表单元素上,可实现输入框的内容与js中的变量进行双向绑定
    1. 如果用在组件上,可实现父值与本地变量之间的双向绑定

该篇文章介绍用在组件的v-model,即第二种

基本用法

使用defineModel()

vite.config.ts中需新增如下配置:

export default defineConfig({
    plugins: [
        vue({
            script: {
              defineModel: true
            }
        })
    ]
})
<!-- Child.vue -->
<script setup>
// defineModel返回的值是Ref类型
const model = defineModel()

function update() {
  model.value++
}
</script>

<template>
  <button @click="update">changeModel</button>
  <div>parent bound v-model is: {{ model }}</div>
</template>
<!-- Parent.vue -->
<Child v-model="count" />

当子组件的model的值发生改变时,父组件的count的值也一起改变

由于defineModel()返回的值是一个ref,所以我们能像修改其他ref一样,在本地修改ref的值,只不过这个ref的改变也会影响到父组件的值。

在子组件中也能使用v-modeldefineModel()返回的ref绑定到一个原生input元素上

// Child.vue
<script setup>
const model = defineModel()
</script>

<template>
  <input v-model="model" />
</template>

v-model 参数

// Parent.vue
<Child 
    v-model:title1="bookTitle1"
    v-model:title2="bookTitle2"    
/>
// Child.vue
<script setup>
const bookTitle1 = defineModel('title1')
const bookTitle2 = defineModel('title2')
</script>

<template>
    <input type="text" v-model="bookTitle1">
    <input type="text" v-model="bookTitle2">  
</template>

defineModel参数

// 不带参数,默认props字段是modelValue
const title1 = defineModel()
// props的字段为modelValue,必传
const title2 = defineModel({
    required: true
})
// v-model:title="xxx",props字段为title
const title3 = defineModel('title')

// v-model:title="xxx",props字段为title,必传
const title4 = defineModel('title', {
    required: true
})

// 针对有自定义修饰符的情况,
const title5 = defineModel('title', {
    // value为解包过的title5的值
    get(value) {
    
    },
    set(value) {
    
    }
})

v-model修饰符

v-model的内置修饰符:.trim .number .lazy,还可以自定义修饰符

// Parent.vue
<Child v-model:title.capitalize="bookTitle">
// Child.vue
<template>
    <div>{{ title }}--{{ titleModifiers }}</div>
    <input v-model="title" type="text">
</template>
<script setup>
const toUpperCase = str => str.charAt(0).toUpperCase() + str.slice(1)

const transformTitle = (str, capitalize) => capitalize ? toUpperCase(str) : str

// titleModifiers: { capitalize: true }
const [title, titleModifiers] = defineModel('title', {
  get(value) {
    console.log('title的值:', value)

    return transformTitle(value, titleModifiers.capitalize)
  },
  set(value) {

    return transformTitle(value, titleModifiers.capitalize)
  }
})
</script>

自定义修饰符可以有多个,比如:

// Parent.vue
<Child v-model:title.capitalize.test="bookTitle">
// Child.vue
<script setup>
const [ title, titleModifier ] = defineModel('title')
// titleModifier为:{ capitalize: true, test: true }
</script>