有意思的bug | el-dialog 嵌套时的生命周期问题

问题描述

涉及三个页面:

首页(page)->弹窗(edit)->子弹窗(inside form)

情况:

首页点编辑时带入form,进入弹窗,弹窗带入form进子弹窗

第一次点击编辑时,弹窗子弹窗有值

第二次编辑时,弹窗子弹窗没有值

涉及代码:

add.vue

javascript 复制代码
<template>
    ///
    <inside-form
        ref="handleInside"
        :enum-data="enumData"
        :type="form.supplierType"
    :inside-form="form">
    </inside-form>
    ///
</template>

<script>
    close() {
      this.form = Object.assign({}, {
        supplierType: 1,
        notes: '',
        attachmentTOList: []
      })
      ///
      this.dialogVisible = false
    },
</script>

insideForm.vue

xml 复制代码
<script>
    props:{
        // 编辑模式时带入表单
        insideForm: {
          type: Object,
          default: () => {
            return {}
          }
        },
    },
    watch:{
        // 编辑模式时分配表单
        insideForm: {
          deep: true,
          immediate: true,
          handler(newObj) {
            // 编辑模式 第一次 进行赋值
            if(newObj && Object.keys(newObj).length && !this.firstType) {
              Object.assign(this.form[this.type], newObj)
            }
          }
        },
    }
    data() {
        return {
            ///
            form: {
                ///
            }
            firstType: null,
        }
    }
    mounted() {
      this.firstType = this.type
    },
</script>

解决办法

在子弹窗加入生命周期观察代码

在页面通过vue插件查看数据走向

发现:

在第一次关闭外层弹窗的时候,首先依次执行了子弹窗的beforeDestory 和 destroyed,最后执行了一次子弹窗的mounted!

私以为:

是关闭外层弹窗调用了close方法,里面改变了this.form的值,导致子组件被重新渲染

其实是:

外层弹窗带了destroy-on-close会导致关闭弹窗时触发了子组件的mounted

因此:

去掉destroy-on-close

发现:

在第一次打开外层弹窗的时候,执行子弹窗的mounted;在关闭外层弹窗的时候,不执行子弹窗的任何生命周期

再次打开外层弹窗的时候,不执行子弹窗的mounted,虽然页面上有值,但是是子弹窗的残留值,并未清空

希望:

能够自己把控子组件的生命周期,从创建到销毁。即希望在正确的地方调用子组件的清空方法

最后的解决方式:

add.vue

ini 复制代码
<template>
    ///
    <inside-form
        v-if="dialogVisible"
        ref="handleInside"
        :enum-data="enumData"
        :type="form.supplierType"
    :inside-form="form">
    </inside-form>
    ///
</template>

insideForm.vue

kotlin 复制代码
destroyed() {
  this.clearCertainForm()
},
methods: {
    // 清空子组件内容
    clearCertainForm() {
      this.form = [///]
      this.merchandiserName = ''
      this.firstType = null
      this.channelDisabled = true
    }
}

在外层弹窗组件引用处,加入v-if,当外层弹窗关闭时,触发v-if将子组件从DOM树上移除,从而触发执行子组件的destory生命周期

在子组件中,在destroyed中进行子组件的清空操作

总结

  • 数据传输出现问题时,加入生命周期观察代码

  • 抽取子组件时,尽量把握子组件的整个生命周期,从创建到销毁

相关推荐
SakitamaX13 分钟前
Nginx安装与实验
服务器·前端·nginx
用户新42 分钟前
V8引擎 精品漫游指南--Ignition篇(中) AST详解 字节码的生成
前端·javascript
岱宗夫up1 小时前
【前端基础】HTML + CSS + JavaScript 基础(三)
开发语言·前端·javascript·css·html
凌云拓界1 小时前
TypeWell全攻略:AI健康教练+实时热力图开发实战 引言
前端·人工智能·后端·python·交互·pyqt·数据可视化
明月_清风1 小时前
三件套快速上手 + 第一个可安装的 PWA(HTTPS + Manifest + 基础 Service Worker)
前端·pwa
菜鸟小芯2 小时前
【GLM-5 陪练式前端新手入门】第三篇:网页导航栏 —— 搭建个人主页的 “指路牌”
前端
明月_清风2 小时前
PWA 到底是什么?它在 2026 年解决了哪些真实痛点?
前端·pwa
甲枫叶2 小时前
【claude产品经理系列13】核心功能实现——需求的增删改查全流程
java·前端·人工智能·python·产品经理·ai编程
蓝帆傲亦2 小时前
Vue.js 大数据处理全景解析:从加载策略到渲染优化的完全手册
前端·vue.js·flutter
不会敲代码12 小时前
React组件通信实战:从Todo应用彻底搞懂父子、子父、兄弟通信
前端·react.js