有意思的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中进行子组件的清空操作

总结

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

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

相关推荐
CPU NULL8 分钟前
Vue 3 前端调试与开发指南
前端·javascript·vue.js
幼儿园技术家1 小时前
多方案统一认证体系对比
前端
十一.3661 小时前
83-84 包装类,字符串的方法
前端·javascript·vue.js
over6971 小时前
深入解析:基于 Vue 3 与 DeepSeek API 构建流式大模型聊天应用的完整实现
前端·javascript·面试
用户4099322502121 小时前
Vue3计算属性如何通过缓存特性优化表单验证与数据过滤?
前端·ai编程·trae
接着奏乐接着舞2 小时前
react useMeno useCallback
前端·javascript·react.js
码农阿豪2 小时前
Vue项目构建中ESLint的“换行符战争”:从报错到优雅解决
前端·javascript·vue.js
xhxxx2 小时前
AI打字机的秘密:一个 buffer 如何让机器学会“慢慢说话”
前端·vue.js·openai
韩曙亮2 小时前
【Web APIs】BOM 浏览器对象模型 ⑥ ( location 对象 | location 常用属性和方法 | URL 简介 )
前端·javascript·dom·url·bom·location·浏览器对象模型
用户21411832636022 小时前
CC-Switch配置切换神器:5秒搞定多设备同步,坚果云让配置永不丢失
前端