Vue3 中 Composition API 如何使用 ref 获取组件实例?
1、获取单个组件实例
<template>
# 定义ref变量名,此时是以字符串的方式而非变量的方式定义的
<div ref="divRef"></div>
<template>
<script setup lang="ts">
// 根据定义的变量名创建ref变量
const divRef = ref();
onMounted(() => {
console.log(divRef);
})
</script>
2、用一个变量获取多个组件实例
我有需求要实现批量操作同类型的组件完成一种行为时,发现文档正文没有对相关内容做出定义
所以我就用了官方不推荐的 getCurrentInstance 这个方法获取到当前组件实例,然后通过 instance.refs 来批量操作
但其实除了框架层面业务层面实际上是不建议使用 getCurrentInstance 这个API的
随后仔细查阅文档发现这个内容被写到了这里
如果有和我上面的需求一直的小伙伴可以看一下
Vue3 提供了一种骚操作
如果想要用一个变量绑定多个
ref,请将ref绑定到一个更灵活的函数上(这是一个新特性)
<div v-for="item in list" :ref="setItemRef"></div>
Options API:
export default {
data() {
return {
itemRefs: []
}
},
methods: {
setItemRef(el) {
if (el) {
this.itemRefs.push(el)
}
}
},
beforeUpdate() {
this.itemRefs = []
},
updated() {
console.log(this.itemRefs)
}
}
Composition API
import { onBeforeUpdate, onUpdated } from 'vue'
export default {
setup() {
let itemRefs = []
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
onBeforeUpdate(() => {
itemRefs = []
})
onUpdated(() => {
console.log(itemRefs)
})
return {
setItemRef
}
}
}
而且 itemRefs 也不一定是数组,也可以是对象,其 ref 可以通过迭代 key 来设置
如果有需要 itemRefs 也可使以响应式的
Vue3 中同时使用 v-if 与 v-for 的注意事项
一般情况下我是不建议在同一个标签同时使用 v-if 和 v-for 的,或许某些情况真的需要这样做
我个人建议还是使用 computed 来对需要 v-for 的数据源进行过滤,从而达到上面的需求,至少从代码可读性上会好很多
下面讲一下 Vue2/3 两个版本中对于这两个同时使用的一些区别
1、Vue2
v-for 的优先级是高于 v-if 的
也就意味着,我们可以在 v-if 的 condition 中使用循环出来的 item 进行判断
2、Vue3
v-if 的优先级高于 v-for
所以以前 Vue2 中的代码在升级之后要么改成 computed 的方式,要么就要注意 condition 无法访问到 v-for 中的 item
组件开发中 v-bind 合并覆盖问题
如果有这样一段代码
<div id="map" v-bind="{ ..., id: 'map1' }" />
# Vue2 结果
<div id="map" />
# Vue3 结果
<div id="map1" />
但如果上面是这样写
<div v-bind="{ ..., id: 'map1' }" id="map" />
# Vue2 结果
<div id="map" />
# Vue3 结果
<div id="map" />
结论是:
Vue2 中的
v-bind永远是独立声明的attr优先级最高,不论顺序。而 Vue3 中的attr最终结果受到声明的前后顺序影响,后声明的永远覆盖先声明的
这点需要注意下
关于 template 的 key 声明
1、Vue2
由于不允许在 template 上定义 key,我们只能在子元素里面逐个定义 key,这很麻烦,但也没办法,谁叫用了 eslint,还是按标准来吧
<template v-for="item in list">
<div :key="'element1-' + item.id">...</div>
<div :key="'element2-' + item.id">...</div>
</template>
2、Vue3
Vue3 允许我们将 key 写到 template 上,这就很 nice
<template v-for="item in list" :key="item.id">
<div>...</div>
<div>...</div>
</template>