1.模板引用
在Vue3当中我当然可以使用JS的原生方法(例如,getElementById
、querySelector
等)。但是其实更推荐方法还是vue的模板引用。
模板引用,我将其称之为“两个ref”:
- 在元素/组件上添加一个
ref
属性 - 声明一个匹配模板中
ref
属性值的ref
(一个响应式变量)
这样在元素/组件被挂载后,就可以通过ref
变量获得对它的直接引用。
<canvas ref="solarCanvas" id="solar" width="1300" height="900"></canvas>
const solarCanvas = ref(null)
2.模板引用无法访问的问题
在一些情况下我们可能会遇到无法访问模板引用的情况,请看下面的这些例子。
组件还未挂载
在下面这中情况下我们访问模板引用会发现结果为null
,因为此时元素还未挂载。
<template>
<canvas ref="solarCanvas" id="solar" width="1300" height="900"></canvas>
</template>
<script setup>
import { ref } from 'vue'
const solarCanvas = ref(null)
console.log(solarCanvas.value);//null
</script>
我们可以借助于声明周期函数或者侦听器来解决这一问题,以确保我们在合适的时机访问模板引用。
onMounted(() => {
console.log(solarCanvas.value) //HTMLCanvasElement{...}
})
watchEffect(() => {
if (solarCanvas.value) {
console.log(solarCanvas.value) //HTMLCanvasElement{...}
}
})
使用条件渲染的方式控制元素
在下面的例子中我使用v-if
来控制<canvas>
,当点击按钮时会切换<canvas>
的显隐状态。
在使用的过程中我们会发现,在handleClick
方法中,即使show
已经被设置为了true
,依旧还是无法访问模板引用。
造成这种现象主要是因为,虽然show
已经被设置为了true
,但元素还没有来的及被挂载。
<template>
<button @click="handleClick">按钮</button>
<br />
<canvas
v-if="show"
ref="solarCanvas"
id="solar"
width="300"
height="300"
style="background-color: pink;"
></canvas>
</template>
<script setup>
import { onMounted, ref, watchEffect } from 'vue'
const solarCanvas = ref(null)
let show = ref(false)
function handleClick() {
show.value = !show.value
if (show.value) {
console.log(solarCanvas.value) //null
}
}
</script>
可以使用nextTick
解决这一问题,它会在DOM更新后立即执行给定的回调函数。
function handleClick() {
show.value = !show.value
if (show.value) {
nextTick(() => {
console.log(solarCanvas.value) //HTMLCanvasElement{...}
})
}
}