昨晚写项目的时候,我有一个需求是需要监听一个对象,当这个对象改变的时候,需要调用子组件里的一个函数,而此时只有当这个对象改变的时候,子组件才会显示出来:
例如如下场景:
父组件:
<template>
<div class="wrapper">
<div class="area">
<Children ref="child" v-if="isShow" />
<button class="btn" @click="isShow = !isShow">子组件显示</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import Children from '../components/Children.vue';
const child = ref()
const isShow = ref<boolean>(false)
watch(
isShow,
(newValue, oldValue) => {
console.log("isShow已经改变")
child.value?.ChildInfo()
},
{},
)
</script>
子组件:
<template>
<div class="wrapper">
子组件
</div>
</template>
<script setup lang="ts">
const ChildInfo = () => {
console.log("我是子组件的一个函数")
}
defineExpose({
ChildInfo
})
</script>
代码里子组件有一个ChildInfo函数,使用defineExpose暴露出去,可以被引用的组件取到。而父组件调用子组件时有一个v-if标签,isShow为false子组件不会被渲染,我们使用watch来监听这个isShow,当isShow改变时,马上调用子组件的ChildInfo函数,打印出一句话。我当时的思路觉得问题不大,可行,但结果确实一直无法调用到这个方法。
此时控制台并没有我们想象一样的打印出需要子组件打印的那句话。为什么呢?因为我们这里在子组件使用了v-if,当isShow为true时此时子组件是没有被渲染的,而监听函数watch在监听到isShow改变后,就马上调用了子组件的方法,子组件还没有渲染完,因此子组件的属性自然是没有取到的。
打印一下看看,此时是undefined,说明没有取到值
怎么才能实现我们的需求呢?
我们可以使用vue中的nextTick函数
vue中的nextTick函数可以让在改变了一些数据并且Vue更新了页面以反映你的改变之后执行一些代码,简单来说这个函数会等待DOM更新完成,才会继续执行。
此时我们再来试一下,成功啦!!
同时也可以这样用:添加async,await,让异步变成同步操作,会等待nextTick函数返回后才会执行下面的代码。具体这两个关键字,我之前的博客有记录到。
又是充实的debug的一天,后端人每天收获一个前端小技巧~~~