vue3和vue2的v-model差异

Vue2 和 Vue3: v-model

v-model主要用于进行表单项的输入绑定,本质上只是一个语法糖,它负责监听用户的输入事件以更新数据。

Vue2 用法

当在自定义组件中使用v-model时,组件接收一个属性value的值,然后通过触发input事件来更新该值,这样便实现了v-model

<my-input v-model="value"></my-input>
<!-- 相当于 -->
<my-input :value="value" @input="value=$event.target.value"></my-input>

v-model 实现

实现my-input组件:

<template>
    <div>
        <input type="text" :value="value" @input="handleInput"/>
    </div>
</template>

<script>
    export default {
        name: "myinput",
        props:{
            value: String
        },
        methods:{
            handleInput(e){
                this.$emit('input', e.target.value) //触发父组件的input事件
            }
        }
    }
</script>

自定义 v-model 属性

v-modelvue2中使用存在一个问题:那就是传递下去的必须是value值,接收的也必须是input事件。但是并不是所有的元素都适合传递value,这时候就可以通过model来指定v-model绑定的值和属性

<template>
    <div>
        <input :value="v" @input="handleInput"/>
    </div>
</template>

<script>
    export default {
        name: "myinput",
        model: {
            prop: 'v', // default: value
            event: 'i', // default: input
        },
        props:{
            v: String
        },
        methods:{
            handleInput(e){
                this.$emit('i', e.target.value) //触发父组件的input事件
            }
        }
    }
</script>

model属性指定了两个属性:propevent,这就是 v-model 的属性和事件名,他们的默认值为valueinput,我们通过修改model属性的 propevent 就实现了自定义。

修饰符

lazy:将触发input事件转为触发change事件,在某些场景下来降低数据同步频率提升性能。

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" />

number:自动将用户的输入值转为数值类型。

<input v-model.number="age" type="number" />

trim:自动过滤用户输入的首尾空白字符

<input v-model.trim="msg" />

Vue3 用法

当在自定义组件中使用v-model时,组件接收一个属性modelValue的值,然后通过触发update:modelValue事件来更新该值:

<my-input v-model="value"></my-input>
<!-- 相当于 -->
<my-input :model-value="value" @update:model-value="value=$event.target.value"></my-input>

v-model 实现

实现my-input组件:

<template>
  <input :value="modelValue" @input="handleInput">
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
   props: ['modelValue'],
   setup(props, context) {
        const handleInput = (e) => {
            context.emit('update:modelValue', e.target.value)
        }
        return {
            handleInput
        }
    }
})
</script>

// 使用
<my-input v-model="value"></my-input>

v-model 参数

Vue3v-model 是接收属性modelValue的值,然后触发事件update:modelValue来更新该值,这个属性名也可以修改,只需要给v-model添加参数即可,比如:v-model:hry,这样就将modelValue换成了hry

<template>
  <input :value="hry" @input="handleInput">
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
   props: ['hry'],
   setup(props, context) {
        const handleInput = (e) => {
            context.emit('update:hry', e.target.value)
        }
        return {
            handleInput
        }
    }
})
</script>

// 使用
<my-input v-model:hry="value"></my-input>;

多个 v-model 绑定

vue3 中新增了 v-model 的参数传递,所以自定义组件可以同时支持多个v-model的绑定:

<my-input v-model:hry="hry" v-model:roy="roy"></my-input>

实现my-input组件:

<template>
    <input :value="hry" @input="e => handleInput(e, 'hry')">
    <input :value="roy" @input="e => handleInput(e, 'roy')">
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
   props: ['hry', 'roy'],
   setup(props, context) {
        const handleInput = (e, name) => {
            context.emit(`update:${name}`, e.target.value);
        }
        return {
            handleInput
        }
    }
})
</script>

修饰符

不同于 vue2 的硬编码,在 vue3 中支持自定义修饰符:

<my-input v-model.cpas="bar"></my-input>

组件接收自定义修饰符:

<template>
    <input :value="modelValue" @input="emitValue">
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
    props: {
        modelValue: String,
        // 组件接收属性modelModifiers对象,对象里面包含多个修饰符,这里默认给个空对象:{}
        modelModifiers: {
            default: () => ({}),
        },
    },
    setup(props, context) {
        // 实现修饰符`capitalize`,将 v-model 绑定的值首字母大写
        const emitValue = (e) {
            let v = e.target.value;
            if (this.modelModifiers.cpas) {
                v = v.charAt(0).toUpperCase() + v.slice(1);
            }
            this.emit('update:modelValue', v);
        }
        return {
            emitValue
        }
    }
})
</script>

组件会接收一个属性为modelModifiers的对象,上面示例给出了默认值{},然后在生命周期函数created中拿到了修饰符capitalize的值为true(因为在上面组件使用时绑定了v-model.capitalize="bar")。

JSRUN前端笔记, 是针对前端工程师开放的一个笔记分享平台,是前端工程师记录重点、分享经验的一个笔记本。JSRUN前端采用的 MarkDown 语法 (极客专用语法), 这里属于IT工程师。