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

总结

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

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

相关推荐
hxjhnct12 分钟前
CSS 伪类和伪元素
前端·javascript·css
❆VE❆13 分钟前
【css】打造倾斜异形按钮:CSS radial-gradient 与抗锯齿实战解析
前端·javascript·css
followYouself16 分钟前
ViewPager+Fragment
android·前端
37方寸18 分钟前
前端基础知识(HTML、CSS)
前端·css·html
u13013023 分钟前
深入解析二维码技术与前端生成方案
前端·二维码
小范馆34 分钟前
STM32F03C8T6通过AT指令获取天气API-下篇
前端·stm32·esp8266-01s
开开心心_Every40 分钟前
无广告输入法推荐:内置丰富词库免费皮肤
服务器·前端·学习·决策树·edge·powerpoint·动态规划
卓怡学长2 小时前
m111基于MVC的舞蹈网站的设计与实现
java·前端·数据库·spring boot·spring·mvc
C_心欲无痕7 小时前
前端实现水印的两种方式:SVG 与 Canvas
前端·安全·水印
尾善爱看海9 小时前
不常用的浏览器 API —— Web Speech
前端