动态修改msg Prop时watch仅首次生效,如何实现模态框自动显隐?
问题解决方法
核心问题:监听目标错误
你在子组件里的watch监听了msg.value,但toRefs(props)返回的msg是一个Ref对象,Vue的watch需要直接监听Ref实例本身,而非它的原始值。这就导致只有首次初始化时触发监听,后续msg更新时监听不到变化。
修复步骤
- 修正watch的监听目标,将
watch(msg.value, ...)改为watch(msg, ...) - 可选优化:处理连续点击相同按钮(msg值重复)的情况,避免watch不触发
- 修复模板中的类绑定语法错误
修改后的子组件代码
<template> <Transition name="fade"> <div v-if="showMsg" class="fixed min-w-[150px] h-max p-2 bg-[var(--back-dash)] flex justify-center items-center z-[20000]" :class="[whereMod, parentStyle]"> <!-- 修正多类绑定的语法错误 --> <span class="text-white">{{ msg }}</span> </div> </Transition> </template> <script setup> const props = defineProps({ msg: String, show: Boolean, where: String, // bottom, up, right, left, bottom-left, bottom-right, up-left, up-right (where in the page to display) parentStyle: String, }) let { msg, parentStyle, show, where } = toRefs(props); let whereMod = ref(null); let showMsg = ref(show.value); let modalTimer = null; // 修正监听目标:直接监听msg这个Ref对象 watch(msg, (newVal) => { if (!newVal) return; // 空值不触发显示(可根据需求调整) showMsg.value = true; // 清除之前的定时器,避免多次点击时定时器叠加导致异常 clearTimeout(modalTimer); modalTimer = setTimeout(() => { showMsg.value = false; }, 1500); }, { immediate: true, deep: true, }) </script>
额外优化:处理重复msg的情况
如果用户连续点击同一个按钮(msg值未变化),watch不会触发。可以在父组件中修改点击逻辑,每次设置msg前先清空:
<template> <button @click="triggerMsg('hightasd')">first</button> <button @click="triggerMsg('brord')">another</button> <DashboardUsedMsgModal where="bottom-left" :msg="msg_modal" :show="false" /> </template> <script setup> import { ref, nextTick } from 'vue'; let msg_modal = ref(''); const triggerMsg = (text) => { // 先清空触发一次watch,再通过nextTick确保更新完成后设置新值 msg_modal.value = ''; nextTick(() => { msg_modal.value = text; }); }; </script>
内容的提问来源于stack exchange,提问作者Abdelrhman Qouay
相关产品推荐
相关产品推荐

