这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
这篇文章我们来讲一下key、ref以及v-for怎么去使用,使用它们的时候需要注意什么,以及它们配合使用的时候在Vue3与Vue2中的差异。
指令介绍
key
官方说,key 特殊 attribute 主要用做 Vue 的虚拟 DOM 算法的提示,以在比对新旧节点组时辨识 VNodes。如果不使用 key,Vue 会使用一种算法来最小化元素的移动并且尽可能尝试就地修改/复用相同类型元素。而使用 key 时,它会基于 key 的顺序变化重新排列元素,并且 key 不再存在的元素将始终被移除/销毁。
根据上述说法,我们看一个例子加深理解,如下:
数据
const kings = ref(["程咬金", "安琪拉", "芈月", "吕布", "李信"])
渲染结果用ol、li元素渲染
<ol>
<li>程咬金</li> //标记1
<li>安琪拉</li> //标记2
<li>芈月</li> //标记3
<li>吕布</li> //标记4
<li>李信</li> //标记5
</ol>
当数据发生变化时,数据为
kings.value=["程咬金", "芈月", "吕布", "安琪拉", "李信"]
无key渲染结果
<ol>
<li>程咬金</li> //标记1
<li>芈月</li> //标记2
<li>吕布</li> //标记3
<li>安琪拉</li> //标记4
<li>李信</li> //标记5
</ol>
有key渲染结果
<ol>
<li>程咬金</li> //标记1
<li>芈月</li> //新标记2
<li>吕布</li> //新标记3
<li>安琪拉</li> //新标记4
<li>李信</li> //标记5
</ol>
从上述例子我们可以看出,当数据发生变化时,无key优先复用存在的相同类型的元素,只改变元素的属性和内容;而有key则会重新排序,key不存在的会被销毁。
在key的使用中,我们需要注意是:
- 有相同父元素的子元素必须有唯一的 key,重复的 key 会造成渲染错误
key我们在v-for中使用居多,但是我们也可以用在其他元素或者组件上:这样是为了触发过渡,让其被替换而不是被修改。比如下面span的写法,我们想触发它的过渡效果,可以给它加上key。
<span :key="text">{{ text }}</span>
ref
ref 被用来给元素或子组件注册引用信息。引用信息将会被注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是那个 DOM 元素;如果用在子组件上,引用就指向组件实例。
简而言之,就是给一个marker,让你可以快速的找到这个元素或组件,值得注意的是ref绑定的时候可以给字符串或者是表达式。
v-for
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression,为当前遍历的元素提供别名。
以上述数据为例,写法如下:
<ol>
<li v-for="king in kings">{{king}}</li>
</ol>
配合使用
在这里我们不仅讲它们三个之间的配合使用,还要讲它们配合使用的时候在Vue3与Vue2中的差异。
key 与 v-for
在指令介绍中,我们讲述了v-for与key的配合使用,在这里我们来讲一下它们配合使用时的另一种情况(v-for作用在 template)。
v-for作用在 template上时,key在Vue2与Vue3的使用方式是不一样的。如下:
//Vue2
<template v-for="king in kings">
<h1 :key="king">{{king}}</h1>
</template>
//Vue3
<template v-for="king in kings" :key="king">
<h1>{{king}}</h1>
</template>
ref 与 v-for
下面我们来用两个例子说明一下它们之间的配合使用,数据用kings=["程咬金", "安琪拉", "芈月", "吕布", "李信"]:
第一个例子 ref="li"
<ol>
<li v-for="king in kings" :key="king" ref="li">{{king}}</li>
</ol>
在我们使用$refs.li来获取标记元素时,在Vue2中我们可以得到一个数组,然而,在Vue3中我们仅仅得到满足这个条件的最后一个元素,即:
<li>李信</li>
第二个例子 :ref="'li'+king"和 :ref="setItemRef"
如果我们在Vue3中想要获取所有标记元素,我们可以做以下操作:
<ol>
<li v-for="king in kings" :key="king" :ref="'li'+king">{{king}}</li>
</ol>
这样我们在使用$refs是可以获得所有标记元素:
Proxy {li程咬金: li, li安琪拉: li, li芈月: li, li吕布: li, li李信: li}
或者我们也可以这样做:
<div id="app">
<ol>
<li v-for="king in kings" :key="king" :ref="setItemRef">{{king}}</li>
</ol>
</div>
<script src="./vue.global.js"></script>
<script>
const { createApp, ref } = Vue
const app = createApp({
setup() {
const kings = ref(["程咬金", "安琪拉", "芈月", "吕布", "李信"])
let itemRefs = [] // 存放元素变量,想操作元素的时候,可以从此变量里面拿值
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
return {
kings,
setItemRef
}
}
})
app.mount("#app")
</script>
总结
-
Vue3 中
v-if总是优先于v-for生效,虽然不建议在同一元素上同时使用两者。 -
在Vue3中,
ref="li"这种写法将不再在$ref中自动创建数组。要从单个绑定获取多个 ref,请将ref绑定到一个更灵活的函数上。 -
v-for作用在template上的情况,Vue2中key要放在其包裹的元素上,Vue3中key要放在template元素上。
想了解更多文章,传送门已开启:回首Vue3目录篇 !