静态绑定
获取单个 dom 元素
<template>
<button ref="domRef">dom</button>
</template>
<script setup>
import { ref, onMounted } from 'vue';
// 声明一个跟 ref 同名的变量即可,来保存元素
const domRef = ref(null);
onMounted(() => {
domRef.value.style.background = "red";
})
</script>
v-for 中使用
<template>
<ul>
<li v-for="item in list" ref="domRef">
{{ item }}
</li>
</ul>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const list = ref([
/* ... */
])
const domRef = ref([]);
onMounted(() => {
console.log(domRef.value)
})
</script>
但需要注意的是,itemRefs 元素数组并不保证与 list 数组为相同的顺序
需要注意的是,访问的时候,要确保 ref 引用值已经成功绑定上元素,我们可以使用以下几种方式确保获取
// onMounted
onMounted(() => {
domRef.value.style.background = "red";
})
// nextTick
nextTick(() => {
domRef.value.style.background = "red";
})
// watchEffect
watchEffect(() => {
if (domRef.value) {
domRef.value.style.background = "red";
}
})
// watch
watch(domRef, val => {
domRef.value.style.background = "red";
})
动态绑定
动态绑定中,分为两种方式,一种是通过将 ref 设置为函数
,第二种则是通过 getCurrentInstance
方法访问当前组件实例上的 $refs
ref 设置函数,获取单个 dom 元素
<template>
<button :ref="handleRef">动态 Ref</button>
</template>
<script setup>
import { ref } from 'vue'
const btnRef = ref(null);
// 赋值动态ref到变量
const handleRef = el => {
if (el) {
btnRef.value = el;
}
}
</script>
ref 的函数回调中,我们能够接受到元素返回值,再动态设置到响应式变量即可
ref 设置函数,v-for 中使用
<template>
<ul>
<li v-for="item in list" :key="item.id" :ref="el => handleRef(el, item)">
<button>{{ item.id }}</button>
</li>
</ul>
</template>
<script setup>
import { ref } from "vue";
const list = ref([{ id: "111" }, { id: "222" }, { id: "333" }]);
let handleRefs = ref([]);
const handleRef = (el, item) => {
console.log(el, item);
handleRefs.value.push(el);
}
</script>
通过 getCurrentInstance 方法
<template>
<ul>
<li v-for="item in list" :key="item.id" :ref="item.id">
<button>{{ item.id }}</button>
</li>
</ul>
</template>
<script setup>
import { getCurrentInstance, onMounted, ref } from "vue";
const { proxy } = getCurrentInstance();
const list = ref([{ id: "111" }, { id: "222" }, { id: "333" }]);
onMounted(() => {
console.log(proxy.$refs["111"]);
})
</script>
这种方式,与 vue2 的 this.$refs
一般无二,只是我们用了 getCurrentInstance
函数在 setup
中获取了当前组件实例以替代 this
获取 vue 实例
需要注意的是,无论通过以上哪种方式获取元素,如果元素为 vue 组件,则需要在子组件中使用 defineExpose 进行暴露。
在父组件中,我们静态绑定 childRef
<template>
<Test ref="childRef"></Test>
</template>
<script setup lang="ts">
import Test from "./components/test.vue";
import { onMounted, ref } from "vue";
const childRef = ref(null);
onMounted(() => {
console.log(childRef.value.btnRef)
})
</script>
在子组件中,我们需要通过defineExpose函数,手动暴露出来ref引用值,该值指向了button元素
<template>
<button ref="btnRef">子组件</button>
</template>
<script setup>
import { ref } from "vue";
const btnRef = ref(null)
defineExpose({
btnRef
})
</script>
网友评论