ref作为在vue里面我们获取元素最常用的一个api,在vue3迎来改造。
在之前vue2使用ref获取元素时,直接在元素上绑定ref属性,在直接使用this.$refs[‘自定义属性名’]就能直接获取。
但是这样也是有一定风险的。因为ref绑定的在元素上,所以当元素没有进行渲染时,是不能通过ref获取到元素的。
<template>
<div>
<div ref="btn">我是一个按钮div>
div>
template>
<script>
export default {
name: 'App',
created() {
console.log(this.$refs.btn); // undefined
this.$nextTick(() => {
console.log(this.$refs.btn) //获取到正确元素
})
},
mounted() {
console.log(this.$refs.btn); //获取到正确元素
}
}
script>
获取v-for的元素
特殊点在于vue2使用这种方法获取v-for的元素时,获取到的是一个数组
<template>
<div>
<div ref="btn" v-for="(item , index) in 3" :key="index">我是一个按钮div>
div>
template>
<script>
export default {
name: 'App',
mounted() {
console.log(this.$refs.btn); //获取到元素数组
}
}
script>
值得庆幸的是,在一般情况下,vue2的获取元素的方法在vue3也完全适用。
当然这说的是结合选项式 API情况下,如果你想在组合式api里面获取一个非数组上的ref绑定的元素
也是极为简单。
<template>
<div id="ref">
<button type="button" ref="butRef" @click="logBtnRef">打印获取的按钮元素</button>
</div>
</template>
<script>
import {ref, onMounted} from 'vue'
export default {
setup() {
let butRef = ref(null)
function logBtnRef() {
console.log(butRef.value);
}
return {
butRef,
logBtnRef
}
}
}
</script>
<style scoped="scoped"></style>
这里我们在渲染上下文中暴露 butRef,并通过 ref=“butRef”,将其绑定到 button作为其 ref。在虚拟 DOM 补丁算法中,如果 VNode 的 ref 键对应于渲染上下文中的 ref,则 VNode 的相应元素或组件实例将被分配给该 ref 的值。这是在虚拟 DOM 挂载/打补丁过程中执行的,因此模板引用只会在初始渲染之后获得赋值。
作为模板使用的 ref 的行为与任何其他 ref 一样:它们是响应式的,可以传递到 (或从中返回) 复合函数中。
但是在vue3里面使用v-for获取元素是拿不到元素数组的,只能获取到遍历出来的最后一个元素。
所以我们只能使用官方提供的方法。
结合选项式 API
<template>
<div>
<button v-for="(item, index) in 3" :key="index" :ref="itemRefs "
@click="consoleBtn">我是一个按钮---{{index}}button>
div>
template>
<script>
export default {
name: 'App',
data() {
return {
itemRefs : []
}
},
methods: {
itemRefs(el) {
if(el) {
this.itemRefs.push(el)
}
},
consoleBtn() {
console.log(this.itemRefs); //拿到的是一个proxy对象
}
}
}
script>
结合组合式 API
<template>
<div>
<button v-for="(item, index) in 3" :key="index" :ref="setItemRef"
@click="consoleBtn">我是一个按钮---{{index}}button>
div>
template>
<script>
import { onBeforeUpdate } from 'vue'
export default {
setup() {
let itemRefs = []
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
onBeforeUpdate(() => {
itemRefs = []
})
function consoleBtn() {
console.log(itemRefs); //拿到的是一个元素数组
}
return {
setItemRef,consoleBtn
}
}
}
script>
注意
1.itemRefs 不必是数组:它也可以是一个对象,其 ref 可以通过迭代的 key 被设置。
2.如有需要,itemRef 也可以是响应式的,且可以被侦听。
3.这是一个新特性,且不向下兼容!