Vue3 模板中的变化
vue3 模板中的变化主要有以下变化:
- 模板必须是单根节点
- 双向绑定的变化
- v-if 与 v-for 优先级与 key 值的变化
1.Fragment
vue2 中组件的模板必须是单根节点,出现多个根节点会报错。
而如果 vue3 组件的模板中出现多个根节点时,会自动将这些节点用fragment
包裹,所以 vue3 模板可出现多个根节点。
2.v-model 双向绑定的变化
vue2 中提供了两种双向绑定:v-model
和.sync
,但在 vue3 中,去掉了.sync
修饰符,只能使用v-model
进行双向绑定。
但为了让v-model
更好的针对多个属性进行双向绑定,vue3 作出了以下变化:
- 当对自定义组件使用
v-model
指令时,绑定的默认属性名由原来的value
变为modelValue
,默认事件名由原来的input
变为update:modelValue
<!-- vue2 默认props属性为value 默认emit事件为input-->
<ChildComponent :value="title" @input="title = $event" />
<!-- 简写为 -->
<ChildComponent v-model="title" />
<!-- vue3 默认props属性为modelValue 默认emit事件为update:modelValue -->
<ChildComponent :modelValue="title" @update:modelValue="title = $event" />
<!-- 简写为 -->
<ChildComponent v-model="title" />
- 去掉了
.sync
修饰符,它原本的功能由v-model
的参数替代
<!-- vue2 -->
<ChildComponent :title="title" @update:title="title = $event" />
<!-- 简写为 -->
<ChildComponent :title.sync="title" />
<!-- vue3 -->
<ChildComponent :title="title" @update:title="title = $event" />
<!-- 简写为 -->
<ChildComponent v-model:title="title" />
- v-model 在组件之间使用时,vue2 中子组件可通过
model
配置属性与事件名,但在 vue3 中移除了model
配置属性。 - 允许自定义
v-model
修饰符(vue2 无此功能)
使用案例:自定义 v-model 修饰符capitalize
,它会自动将 v-model 绑定输入的字符串值第一个字母转为大写:
<!-- 父组件 -->
<MyComponent v-model.capitalize="myText" />
当 v-model 不存在参数时,子组件通过modelModifiers
这个 prop 属性名访问自定义修饰符,它默认值是一个空对象。
当 v-model 存在参数时,子组件的 prop 名将是{{arg}}+Modifiers
,子组件将通过该属性名访问修饰符。如:父组件为<MyComponent v-model:title.capitalize="myText">
时,此时 prop 名为titleModifiers
。
<!-- 子组件 -->
<template>
<input type="text" :value="modelValue" @input="emitValue" />
</template>
<script>
import {defineProps,defineEmits} from 'vue';
setup(){
//声明相应的属性与事件名
const props = defineProps({
modelValue: String,
modelModifiers: { default: () => ({}) }
})
const emit = defineEmits(['update:modelValue'])
function emitValue(e) {
let value = e.target.value
//props.modelModifiers.capitalize = true 表示自定义v-model修饰符capitalize 存在
if (props.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
emit('update:modelValue', value)
}
}
</script>
3.v-if v-for key
3.1 v-if 与 v-for 的变化
vue2 中v-for
的优先级高于 v-if
,如果同时使用这两个指令可能会影响性能,为此我们必须做一些操作来避免性能上的损失。
- 情况一:v-if 不需要使用 v-for 循环内的 item 进行判断时
- 在外层先套一个
<template>
标签,并在该标签上使用 v-if 进行判断,<template>
标签内部再使用 v-for 进行渲染。
- 情况二:v-if 需要使用 v-for 循环内的 item 进行判断时
- 先使用 computed 计算属性代替 v-if 对 数据 进行过滤,再将过滤后的数据使用 v-for 进行渲染。
所以为了避免这个设计缺陷, vue3 中v-if
的优先级高于 v-for
,并且同时使用这两个指令会导致报错。
3.2 key
vue2 中,不能给<template>
标签添加 key 属性,有时要给<template>
标签的每一个子节点中,会给开发者带来一定的麻烦。
而 vue3 中,当使用<template>
进行v-for
循环时,只需要把key
值放到<template>
中,而不是它的子元素中
当使用v-if v-else-if v-else
分支的时候,不再需要指定key
值,因为 vue3 会自动给予每个分支一个唯一的key
,即便要手工给予key
值,也必须给予每个分支唯一的key
,不能因为要重用分支而给予相同的 key。