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

总结

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

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

相关推荐
m0_748255028 分钟前
前端常用算法集合
前端·算法
真的很上进22 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web1309332039828 分钟前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2341 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1231 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~2 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语2 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg2 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww2 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest