作者:小丁 | 日期:2025-03-04
嘿,各位前端探险家 !今天我们要一起破解一个让人抓狂的小谜题:为什么我在 Vue 子组件里辛辛苦苦写的 mounted()
,点击“添加”按钮时就是不打印日志? 是代码叛变了,还是我打开方式不对?别急,带上你的咖啡 ☕,跟着我一起抽丝剥茧,揭开这个“生命周期失踪案”的真相!
mounted
想象一下,你是一个前端侦探,接到一个紧急任务:有个 Vue 项目,子组件
的 mounted()
死活不执行。代码是这样的:
mounted() {
console.log('Initial form.sampleSendTime:', this.form.sampleSendTime);
}
你信心满满地点击“添加”按钮,期待控制台跳出 2025-03-04T07:27:26.058Z
(一个帅气的 ISO 时间戳)。结果呢?一片寂静,控制台冷漠得像冬天的北极 ❄️。这到底是怎么回事?让我们从犯罪现场(代码)开始调查吧!
先来看看父组件怎么调用这个子组件的(src/views/tools/fake-strategy/index.vue
):
<ave-form
:clist="clist.admins"
:value="aveForm"
:visible="aveFormVis"
:operate-type="operateType"
@close="onAveFormClose"
/>
“添加”按钮的逻辑是这样的:
public handleAdd() {
this.aveForm = Object.assign({}, {});
this.aveFormVis = true;
this.operateType = 'add';
}
乍一看,好像没啥问题啊!点击“添加”,aveFormVis
变成 true
,子组件的对话框(
)应该弹出,mounted
也应该触发,对吧? 但真相往往藏在细节里。注意到了吗?这里没有 v-if
,子组件是始终存在于 DOM 中的,只是通过 :visible
控制显示与否。这是个关键线索!
子组件
用的是 Element UI 的
:
<el-dialog
:visible="visible"
:before-close="handleTopRightClose"
destroy-on-close
...
>
:visible="visible"
:从父组件的 aveFormVis
绑定过来,控制对话框开关。destroy-on-close
:关闭时销毁对话框内部内容,下次打开时重新创建。理论上,destroy-on-close
应该让子组件在关闭后销毁,点击“添加”时重新挂载,触发 mounted
。但等等!我们发现,destroy-on-close
只影响
内部的 DOM 和状态,并不会销毁整个
组件实例。换句话说,
就像个“僵尸组件” ♂️,一直活着,只是藏起来了!
为了让大家更直观地理解,我用 SVG 画了个图:
父组件加载 创建 mounted() 触发一次 点击“添加”只是更新 :visible mounted() 不触发!<svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="20" width="300" height="160" fill="#f0f0f0" stroke="#666" stroke-width="2"/>
<text x="60" y="40" font-size="16" fill="#333">父组件加载text>
<circle cx="90" cy="80" r="20" fill="#ff9999"/>
<text x="70" y="85" font-size="12" fill="#fff"><ave-form> 创建text>
<text x="120" y="80" font-size="14" fill="#333">mounted() 触发一次text>
<path d="M 110 80 Q 200 120 290 80" stroke="#666" stroke-width="2" fill="none"/>
<text x="180" y="140" font-size="14" fill="#666">点击“添加”只是更新 :visibletext>
<text x="180" y="160" font-size="14" fill="#ff0000">mounted() 不触发!text>
svg>
这个图展示了:
在父组件初次渲染时就挂载了,mounted
只执行一次。之后点击“添加”,只是让对话框可见,组件实例没销毁,也没重新挂载。
经过一番侦查,我们锁定了“凶手”:
v-if
,
在页面加载时就创建,mounted
在那时就执行了。aveFormVis
从 false
变为 true
,只是改变了 :visible
,没有触发重新挂载。destroy-on-close
的误解:它只销毁对话框内部内容,
的 Vue 实例依然存活。简单来说,你期待的“每次打开都触发 mounted
”被 Vue 的生命周期规则无情打破了!
mounted
重获新生别慌,我们有办法让 mounted
在点击“添加”时复活!以下是几个“解药”:
v-if
给组件“断电重启” ⚡修改父组件:
<ave-form
v-if="aveFormVis"
:clist="clist.admins"
:value="aveForm"
:visible="aveFormVis"
:operate-type="operateType"
@close="onAveFormClose"
/>
v-if
让
在 aveFormVis
为 false
时销毁,为 true
时重新创建。每次点击“添加”,mounted
都会开心地跳出来喊:“我又活了!” visible
,曲线救国 如果不想改父组件,可以在子组件加个“眼线”:
@Watch('visible')
watchVisible(newVal: boolean) {
if (newVal) {
console.log('Dialog opened, Initial form.sampleSendTime:', this.form.sampleSendTime);
}
}
mounted
打印日志。简单粗暴,但够用!在 mounted
加个条件:
mounted() {
if (this.visible) {
console.log('Initial form.sampleSendTime:', this.form.sampleSendTime);
}
}
@Watch('visible')
watchVisible(newVal: boolean) {
if (newVal) {
console.log('Initial form.sampleSendTime:', this.form.sampleSendTime);
}
}
经过这场技术侦探之旅,我们不仅找回了失踪的 mounted()
,还学到了 Vue 组件生命周期的一个小秘密:挂载不是你想触发就能触发的,得看组件有没有“重生”机会!用 v-if
是最直接的解法,就像给组件按了个“重启键” 。
试试方案 1,点击“添加”,控制台会欢快地输出:
Initial form.sampleSendTime: 2025-03-04T07:27:26.058Z
怎么样,是不是有种破案成功的成就感? 下次遇到类似问题,别忘了检查组件是不是“僵尸”状态哦!
把
想象成一个“智能灯泡” :
v-if
:灯泡一直插着电,开关只是控制亮不亮,装灯泡的动作(mounted
)只发生一次。v-if
:每次要亮时都重新插电,装灯泡的仪式感满满,每次都触发!好了,今天的探险就到这里!有什么前端迷案困扰着你?评论区告诉我,我带着放大镜 来帮你破解!✌️