Vue3中使用ref获取元素节点
本文介绍在vue3
的setup
中使用composition API
获取元素节点的几种方法:
静态绑定
仅仅需要申明一个ref
的引用,用来保存元素,在template
中,不必bind
引用(:ref="domRef"
),只需要声明一个同名的ref
属性(ref="domRef"
)即可。
<script setup> import { ref, onMounted } from 'vue' // 声明一个ref引用,来保存元素 const domRef = ref(null) onMounted(() => { domRef.value.style.background = "red" }) </script> <template> <!-- 这里只需要同名即可 --> <button ref="domRef">dom</button> </template>
需要注意的是,访问的时候,要确保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" })
v-for中使用
在使用v-for
进行静态绑定时,仅需要注意以下两点:
- 要与
v-for
在同级 ref
是一个数组ref([])
<script setup> import { ref, onMounted } from 'vue' const list = ref([ /* ... */ ]) const itemRefs = ref([]) onMounted(() => console.log(itemRefs.value)) </script> <template> <ul> <li v-for="item in list" ref="itemRefs"> {{ item }} </li> </ul> </template>
但需要注意的是,itemRefs
元素数组并不保证与list
数组为相同的顺序。
动态绑定
动态绑定中,分为两种方式,一种是通过将ref
设置为函数,第二种则是通过getCurrentInstance
方法访问当前组件实例上的$refs
;
ref设置函数
<template> <button :ref="handleRef">动态Ref</button> </template> <script setup> import { shallowRef } from 'vue' const btnRef = shallowRef(null) // 赋值动态ref到变量 const handleRef = el => { if (el) { btnRef.value = el } } </script>
ref
的函数回调中,我们能够接受到元素返回值,再动态设置到响应式变量即可;
当然,通过设置函数回调的方式,我们也能非常灵活得进行进一步的封装。
<template> <ul> <li v-for="item in list" :key="item.id" :ref="(el) => handleLiRef(el, item)"> <button>{{ item.id }}</button> </li> </ul> </template> <script setup> import { ref } from "vue" const list = ref([{ id: "111" }, { id: "222" }, { id: "333" }]) const handleLiRef = (el, item) => { console.log(el, item) } </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>