本文最后更新于 2025年1月26日 凌晨
前言
在此次Vue 3.4的更新忠,最引人注目的莫过于defineModel的正式登场。此新特性是对Vue组件间通信机制的一次重要升级,旨在简化双向数据绑定的实现,让开发者能够以更优雅、高效的方式处理父子组件间的状态共享。
vue2中的v-model的使用与实现方式
v-mode本质是一种语法糖,它简化了表单控件与数据之间的双向绑定过程,在vue2中 其是v-bind:value 与 @input 的 一种简写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <!--v-model写法--> <input v-model="message"> <!--等价于--> <input :value="message" @input="message = $event.target.value">
// 自定义组件绑定多个数据 -------------------------------------- <!--父组件--> <son-com :first="first" :second="second" @update:first="toUpdateFirstDateHandler" @update:second="toUpdateSecondDateHandler"> </son-com>
<!-- SonCom.vue --> <template> <!-- 假设这里有一些与first和second相关的交互 --> </template> <script> export default { props: ['first', 'second'], data() { return { // 内部状态,如果有的话 }; }, watch: { first(newVal) { this.$emit('update:first', newVal); // 监听first变化 }, second(newVal) { this.$emit('update:second', newVal); // 监听second变化 } }, // 或者在methods中根据具体逻辑触发事件 } </script>
|
可以看到,如果想要更新一些状态,过程还是比较繁琐的,vue2后续又出现了一个修饰符 .sync ,简化了父组件的绑定操作,比如双向绑定多个状态可以改写为:
1 2 3
| <son-com :first.sync="first" :second.sync="second"> </son-com>
|
vue3中的v-model的使用
vue3的v-model相比vue2来说 更加友好,
- 其语法糖由默认的 :value 与@input 改变未 :modelValue 与@uptate:modelValue, 你可以自定义触发的事件名称。
- v-mode可以直接绑定数组或者对象的属性值,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <my-component v-model="user.name"></my-component> <script setup> const user = ref({ name:'wang' }) </script>
<template> <input type="text" :value="props.modelValue" @input="updateName($event.target.value)"> </template>
<script setup> const props = defineProps({ modelValue: { type: String, default: '' } });
const emit = defineEmits(['update:modelValue']); const updateName = (newValue) => { emit('update:modelValue', newValue); }; </script>
|
vue3.4中的defineModel的使用
下面是defineModel的简单使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <my-component v-model:person="person" v-model:job="job"></my-component>
<template> <input type="text" v-model="person"> <input type="text" v-model="job"> <!-- 或其他逻辑,根据组件需要更新modelValue --> </template>
<script setup> const person = defineModel('person') const job = defineModel('job') </script>
|
defineModel看似是违背了数据的单项流动原则 其实不然 ,该宏函数只是隐藏了制造中间变量去接受prop的值与更新input绑定的值的过程,
其本质可以简化为以下模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <template> <input v-model="model" /> </template> <script setup lang="ts"> import { ref, watch } from "vue"; const props = defineProps(["modelValue"]); const emit = defineEmits(["update:modelValue"]); const model = ref(); watch( () => props.modelValue, () => { model.value = props.modelValue; } ); watch(model, () => { emit("update:modelValue", model.value); }) </script>
|
结语
vue3.4版本的更新 除了带来了defineModel这个宏函数 ,还做了计算属性的优化与模板解析的优化,其中还有v-bind的同名简写(比如,:name=’name’ 现在可以简写为 :name),是一次比较全面的更新,
对开发者更友好,对性能也有很大的提升,有条件的,可以将vue版本更新至3.4以上。
vue3.4官方博客更新介绍