本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-03-22
除之前提到 v-model 外,还有一系列关于模板的变更。
特殊的 key attribute 被用于提示 Vue 的虚拟DOM算法来保持对节点身份的持续跟踪。这样Vue可以知道何时能够重用和修补现有节点,以及何时需要对它们重新排序或重新创建。
Vue 2.x 建议在 v-if/v-else/v-else-if
的分支中使用 key。
但是现在我们不再建议在条件分支中继续使用 key attribute,因为没有为条件分支提供 key 时,也会自动生成唯一的 key。
非兼容变更体现在如果你手动提供了 key,那么每个分支都必须使用一个唯一的 key。因此大多数情况下都不需要设置这些 key。
<!-- Vue 2.x 建议使用 -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="a">No</div>
<!-- Vue 3.x 建议移除key -->
<div v-if="condition">Yes</div>
<div v-else>No</div>
<!-- Vue 3.x 如果提供了必须保持key值的唯一性,所以大多数情况下不需要设置 -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="b">No</div>
针对v-for
,有这样的变更,以前<template>
标签不能拥有 key
值,可以为其每个节点分别设置key
值,而在Vue3中,key
则应该被设置在<template>
上。
<!-- Vue 2.x -->
<template v-for="item in list">
<div :key="item.id">...</div>
<span :key="item.id">...</span>
</template>
<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>
2.x 版本中在一个元素上同时使用 v-if
和 v-for
时,v-for
会优先作用。而 3.x 版本中 v-if
总是优先于 v-for
生效。
由于语法上存在歧义,建议避免在同一元素上同时使用两者。比起在模板层面管理相关逻辑,更好的办法是通过创建计算属性筛选出列表,并以此创建可见元素。
在Vue2.x 中如果动态绑定一个全是attribute 的对象,可以这样使用:
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
但存在这样的问题,如果一个元素同时定义了 v-bind="object"
和一个相同的单独的 property,那么这个单独的 property 总是会覆盖 object 中的绑定。
<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="red"></div>
在 3.x,如果一个元素同时定义了 v-bind="object"
和一个相同的单独的 property,那么声明绑定的顺序决定了它们如何合并。
<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="blue"></div>
<!-- template -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- result -->
<div id="red"></div>
在Vue2.x 中,传递给带有 v-on 的组件的事件监听器只有通过 this.$emit
才能触发。要将原生 DOM 监听器添加到子组件的根元素中,可以使用 .native
修饰符。
<my-component
v-on:close="handleComponentEvent"
v-on:click.native="handleNativeClickEvent"
/>
而在Vue3中,移除了.native
修饰符,新增的 emits 选项允许子组件定义真正会被触发的事件。
<my-component
v-on:close="handleComponentEvent"
v-on:click="handleNativeClickEvent"
/>
<!-- MyComponent.vue -->
<script>
export default {
emits: ['close'], // 在emits选项中不再提供native相关的事件名称,就可以将原生DOM监听器添加到子组件的根元素中
}
</script>
对于子组件中未被定义为组件触发的所有事件监听器,Vue 现在将把它们作为原生事件监听器添加到子组件的根元素中 (除非在子组件的选项中设置了 inheritAttrs: false
)。
所以需要确保所有组件都使用 emits
选项记录其除原生事件外的自定义事件。
在 Vue 2 中,在 v-for
里使用的 ref
attribute 会用 ref 数组填充相应的 $refs
property。当存在嵌套的 v-for
时,这种行为会变得不明确且效率低下。
在 Vue 3 中,这样的用法将不再在 $ref
中自动创建数组。要从单个绑定获取多个 ref,请将 ref
绑定到一个更灵活的函数上 (这是一个新特性):
<template>
<div v-for="item in list" :ref="setItemRef"></div>
</template>
<!-- composition api -->
<script>
import { onBeforeUpdate, onUpdated } from 'vue'
export default {
setup() {
// 如果是使用 options api, 则可以将itemRefs挂载在data选项上,将setItemRef定义在methods选项中
let itemRefs = []
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
onBeforeUpdate(() => {
itemRefs = []
})
onUpdated(() => {
console.log(itemRefs)
})
return {
setItemRef
}
}
}
</script>
需要注意的是,itemRefs
不必是数组。它也可以是一个对象,其 ref
会通过迭代的 key 被设置。如果需要,itemRef
也可以是响应式的且可以被监听。