1、内容系个人翻译自 Vue 3.0 Beta 版文档中 Migration From Vue 2 章节
2、不一定准确,欢迎交流(别人都翻过几百遍了吧,再说也没人看)
3、水平有限、随时太监
· 从Vue 2到Vue 3的迁移指南之破坏性特性(一、全局API)
· 从Vue 2到Vue 3的迁移指南之破坏性特性(二、全局API的tree-shaking)
v-model
概览
这些变化可以概括为:
- 破坏性的: 当用在 自定义组件 上的时候,
v-model
的 prop 与 event 的默认名已变更:- prop:
value
->modelValue
; - event:
input
->update:modelValue
;
- prop:
- 破坏性的:
v-bind
的.sync
修饰符以及model
选项已删除,取而代之的是v-model
的一个参数; - 新的: 现在可以在一个组件上使用多个
v-model
来绑定数据了; - 新的: 新增了自定义
v-model
修饰符的功能。
更多信息请继续阅读!
Introduction
当 Vue 2.0 发布的时候,v-model
指令要求开发者固定使用 value
属性(作为数据传递)。而如果开发者需要使用多个不同参数的话,那就只能使用 v-bind.sync
来实现。此外,v-model
和 value
之间这种硬编码关系也会导致我们在使用原生或自定义元素时产生一些问题。
在 2.2 的时候我们引入了 model
这个组件选项,它允许一个组件在使用 v-model
的时候定制 prop 和 event,但是实际上还是只能在组件上使用一个 v-model
。
而在 Vue 3 中,这个用于双向绑定的 API 会变得更标准化以减少混乱的地方,同时开发者也可以更灵活地使用 v-model
指令。
2.x 语法
在 2.x 里,使用 v-model
等同于向组件传递一个 value
属性,同时监听一个 input
事件:
<ChildComponent v-model="pageTitle" />
<!-- 是以下代码的简写: -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
如果我们想修改 prop 和 event 值的命名,我们则需要通过在一个子组件添加 model
选项:
<!-- ParentComponent.vue -->
<ChildComponent v-model="pageTitle" />
// ChildComponent.vue
export default {
model: {
prop: 'title',
event: 'change'
},
props: {
// 允许将 'value' 属性作其他用途
value: String,
// 使用 'title' 作为 prop
title: {
type: String,
default: 'Default title'
}
}
}
所以,在这种状况下,v-model
是以下代码的简写:
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
使用 v-bind.sync
有些时候,我们可能需要对一个属性进行双向绑定(除了已经用 v-model
绑定的那个属性以外的情况)。这种情况我们推荐使用 update:myPropName
这种模式去触发事件;举例来说,对于前面那个例子,我们可以通过这方式达到向子组件的 title
属性传递一个新值的目的:
this.$emit('update:title', newValue)
这样一来父组件就可以监听到这个事件,然后更新本地数据,像这样:
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
我们可以使用 .sync
修饰符来简写上述内容:
<ChildComponent :title.sync="pageTitle" />
3.x 语法
在 3.x 里,使用 v-model
等同于向组件传递一个 modelValue
属性,同时监听一个 update:modelValue
事件:
<ChildComponent v-model="pageTitle" />
<!-- 是以下代码的简写: -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
v-model
参数
要修改一个model的名称的话,现在我们可以给 v-model
传递一个 参数 以取代此前的 model
选项:
<ChildComponent v-model:title="pageTitle" />
<!-- 是以下代码的简写: -->
<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
的修饰符
除了 2.x 上硬编码的 v-model
相关的修饰符、像 .trim
这样的外,在 3.x 上我们支持自定义修饰符了:
<ChildComponent v-model.capitalize="pageTitle" />
在 自定义事件 章节中获取更多关于 v-model
修饰符的信息。
迁移策略
推荐:
-
找到代码库中使用到
.sync
的地方,并将其替换为v-model
:<ChildComponent :title.sync="pageTitle" /> <!-- 替换成 --> <ChildComponent v-model:title="pageTitle" />
-
对于所有不带参数的
v-model
,确保将它所使用的 props 名和事件名分别修改成modelValue
andupdate:modelValue
:<ChildComponent v-model="pageTitle" />
// ChildComponent.vue export default { props: { modelValue: String // 在这之前是 `value: String` }, methods: { changePageTitle(title) { this.$emit('update:modelValue', title) // 在这之前是 `this.$emit('input', title)` } } }
后续
获取更多关于新的 v-model
语法的信息,请参阅: