简单概述
非兼容更改:
- 用于自定义组件时,
v-model
prop和事件默认名称已更改:- prop : value -> modelValue
- 事件: input -> update: modelValue;
- v-bind 的 .sync 修饰符和组件的 model 选项已移除,可在 v-model 上加一个参数代替
新增:
- 现在可以在同一个组件上使用多个 v-model 绑定;
- 现在可以自定义 v-mdoel 修饰符;
接下来一一介绍
2.x语法
在Vue2组件中,使用 v-model 指令必须使用名为 value 的prop。如果不使用这个,必须 使用 v-bind.sync
,此外,由于 v-model 和 value 之间的这种硬编码关系,产生如何处理原生元素和自定义元素的问题
后来,在Vue2.2中引入了 model 组件选项,允许组件自定义用于 v-model 的prop和事件。但是,这里只允许在组件上使用一个 v-model
<childComponent v-model="pageTitle"/>
// 在组件上使用 v-model 相当于绑定 value prop 并触发 input 事件
<childComponent :value="pageTitle" @input="pageTitle = $event"/>
如果这时想要更改 prop 或事件名称,则需要在 ChildCompoent
组件中添加 model 选项:
// 在 childComponent 父组件内写
<childCompoent v-model="pageTitle">
// 在 childCompoent 组件内部写
export default {
model: {
prop: 'title',
event: 'change'
},
props: {
// 允许 value 属性用于其他用途
value: String,
// 用 title 代替 value 作为 model 的 prop
title: {
type: String,
default: 'title'
}
}
}
这样简写为:
<ChildCompoent :title="pageTitle" @change="pageTitle = $event">
使用v-bind.sync
在某些情况下,我们可能需要对某一个Prop进行 双向绑定(除了前面的 v-model 绑定 prop的情况)
推荐使用 update: myPropName
抛出事件。例如:对于上面案例中带有 title prop 的 ChildComponent ,我们可以通过下面的方式将分配新 value 的意图传达给父级:
this.$emit('update: title', newValue);
在父组件可以监听这个事件,并更新到本地的 data property :
<ChildComponent :title="pageTitle" @update: title = "pageTitle = $event" />
两个使用 .sync 修饰符缩写形式为:
<ChildCompoent :title.sync="pageTitle" />
3.x语法
双向数据绑定的API已经标准化,以减少开发者在使用 v-model 指令时的混淆,更加灵活
自定义组件上的 v-model 相当于 modelValue prop 并接收抛出的 update: mdoelValue
事件:
<ChildCompoent v-model="pageTitle" />
// 简写前为:
<ChildCompoent
:modelValue="pageTitle"
@update: modelValue="pageTitle = $event"
/>
v-model参数
若需要更改 model 的名称,我们现在可以为 v-model 传递一个参数,以作为组件内 model 选项的替代:
<ChildComponent
v-model:title="pageTitle"
/>
<!-- title指的是 Prop Name -->
<!-- pageTitle指的是 Data to bind -->
<!-- 未简写前 -->
<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
/>
可以作为 .sync
修饰符的替代,而且允许我们在自定义组件上使用多个 v-model
<ChildComponent
v-model:title="pageTitle"
v-model:content="pageContent"
/>
<!-- 未简写前 -->
<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
:content="pageContent"
@update:content="pageContent = $event"
/>
v-model 修饰符
Vue还支持自定义修饰符:
<ChildComponent v-model.capotalize="pageTitle" />
迁移策略
Vue2项目迁移到Vue3,所涉及的修改
- 将所有使用
.sync
部分并将其替换为v-model
:
<ChildComponent :title.sync="pageTitle" />
<!-- 替换成 -->
<ChildComponent v-model:title="pageTitle" />
- 对于所有不带参数的 v-model ,确保分别将 prop 和 event 命名更改为
modelValue
和update: modelValue
<ChildComponent v-model="pageTitle" />
// ChildComponent 组件内部
export default {
prop: {
modelValue: String // 以前是 'value: String'
},
emits: ['update: modelValue'],
methods: {
changeTitle(title) {
this.$emit('update: modelValue', title)
// 以前的用法是 'this.$emit('input', title)'
}
}
}
如果需要回味一下 .sync 的用法,这有 入口 .sync高级用法