Vue3如何在父元素ref可用时加载子组件?
解决方案
核心原因
Vue 的 $refs 并非响应式数据,仅在组件**挂载完成(mounted 钩子阶段)**后才会被填充。计算属性无法追踪 $refs 的变化,所以不会自动更新;而模板中直接使用 v-if="$refs.refCurrentSlot" 时,首次渲染阶段 $refs 尚未赋值,因此子组件不会加载,直到后续组件更新(比如 mouseover 触发)才会检测到 $refs 存在。
方法一:通过挂载钩子+状态变量控制
利用组件的 mounted 钩子(此时 DOM 已渲染完成,$refs 可用),设置一个状态变量来控制子组件的加载:
<template> <div ref="refCurrentSlot" @mouseover="addCssClass" @mouseleave="removeCssClass"> <div class="tooltipHolder"></div> </div> <Tooltip v-if="isRefReady" :tooltip-holder="() => $refs.refCurrentSlot.querySelector('.tooltipHolder')"></Tooltip> </template> <script> export default { data() { return { isRefReady: false } }, mounted() { // 组件挂载后,$refs 已被赋值,此时开启子组件加载 this.isRefReady = true; // 若父元素依赖异步数据渲染(比如接口返回后才显示),需用 $nextTick 确保 DOM 更新完成 // this.$nextTick(() => { // this.isRefReady = true; // }); } } </script>
方法二:直接绑定目标元素的 ref(更简洁)
无需通过父元素 querySelector,直接给 tooltipHolder 绑定 ref,再传递给子组件:
<template> <div ref="refCurrentSlot" @mouseover="addCssClass" @mouseleave="removeCssClass"> <div ref="tooltipHolder" class="tooltipHolder"></div> </div> <Tooltip v-if="tooltipHolder" :tooltip-holder="() => tooltipHolder"></Tooltip> </template> <script> export default { data() { return { tooltipHolder: null } }, mounted() { this.tooltipHolder = this.$refs.tooltipHolder; } } </script>
为什么计算属性无效?
计算属性仅会追踪 Vue 的响应式依赖(比如 data、props 中的变量),而 $refs 不属于响应式数据,因此当 $refs 从 undefined 变为 DOM 元素时,计算属性不会重新计算,自然无法更新状态。
内容的提问来源于stack exchange,提问作者Pad
相关产品推荐
相关产品推荐

