el-dialog关闭再打开后窗口内容不刷新问题及解决

 更新时间:2024年02月29日 10:06:35   投稿:jingxian  
这篇文章主要介绍了el-dialog关闭再打开后窗口内容不刷新问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

页面中有增加和编辑两个功能,由于弹窗样式都是一样的,于是将它拆分成一个子组件,父组件把状态传给子组件,子组件根据这个状态判断是做编辑操作还是新增操作.

编辑:

添加:

问题一:但是这样遇到了一个问题,在编辑时,只有第一次点编辑时,回显的数据才能正确显示。

随后再点其他部门的编辑,数据显示不正确了,还是第一次点开的那个部门的数据.

原因:现在的代码中,获取部门详情这个动作在子组件的created中发出的,而created钩子只会执行一次:后续点击关闭弹层时,子组件被没有销毁,它只是隐藏了。

问题二:点击编辑之后再点击添加,添加表单中也会出现部门详情数据

原因:是关闭弹窗时,子组件被没有销毁,它只是隐藏了,也没有清空里面表单的数据

我们先来看问题一数据不更新

问题一:回显数据不更新

解决方案一:在父组件中

给父组件中的el-dialog添加destroy-on-close属性

查阅了 Dialog 对话框 相关文档:

我们可以给它加上这个属性

<el-dialog
        :title="isEdit?'编辑':'新增'"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        @close="resetForm"
      >
        <!-- element ui 中dialog的方法destroy-on-close,关闭时销毁 Dialog 中的元素 -->
        <deptDialog
          :id="fatherId"
          :origin-list="originList"
          :is-edit="isEdit"
          destroy-on-close
          @success="doSuccess"
          @doClose="dialogVisible=false"
        />
      </el-dialog>

解决方案二:直接在内容上加上属性 v-if="dialogVisible"

v-if="dialogVisible",关闭和打开弹层,销毁和创建组件

v-if会由false=>true,会触发beforeCreate,created,beforeMount,mounted 钩子。

由true=>false,会触发 beforeDestroy,destroyed 钩子。

所以我们只要给它加上v-if,取值为控制弹窗显示隐藏的值,我们打开弹窗时它就会重新重建,关闭弹窗的话就会销毁,

这样每次打开弹窗都会执行created钩子里的获取部门详情函数,问题就解决了

这样做虽然简单,但是它会有性能消耗,其中的ajax请求也会随着组件的创建和销毁重复执行

<el-dialog
        :title="isEdit?'编辑':'新增'"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        @close="resetForm"
      >
        <!-- 解决数据不更新的问题:v-if="dialogVisible",关闭和打开弹层,销毁和创建组件 -->
        <deptDialog
          v-if="dialogVisible"
          :id="fatherId"
          :origin-list="originList"
          :is-edit="isEdit"
          @success="doSuccess"
          @doClose="dialogVisible=false"
        />
      </el-dialog>

解决方案三:在父组件中通过引用找到子组件

在父组件中,每次打开弹层时,找到子组件,要求它去发请求获取详情

添加ref引用:

<el-dialog
        :title="isEdit?'编辑':'新增'"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        @close="resetForm"
      >
        <!-- 添加引用: ref="deptDialog" -->
        <deptDialog
          :id="fatherId"
          ref="deptDialog"
          :origin-list="originList"
          :is-edit="isEdit"
          @success="doSuccess"
          @doClose="dialogVisible=false"
        />
      </el-dialog>

在编辑时:找到子组件,要求它去发请求获取详情

// 编辑
    doEdit(id) {
      //isEdit设为true,表示当前状态为编辑
      this.isEdit = true
      this.fatherId = id
      this.dialogVisible = true
      // 解决数据不更新的问题: this.$refs.deptDialog.loadDepartDetail()
      // 注意:由于DOM更新是异步的,此处要用$nextTick()
      this.$nextTick(() => {
        this.$refs.deptDialog.loadDepartDetail()
      })
      //或者放在宏任务里,如延时器中
      // setTimeout(() => {
      // this.$refs.deptDialog.loadDepartDetail()
      // }, 0)
    },

子组件: 

created() {
    //加载部门负责人列表数据
    this.loadEmployeesSimples()
    //如果为编辑状态,获取部门详情
    if (this.isEdit) this.loadDepartDetail()
  },

解决方案四:在子组件内监听id的变化(不推荐使用)

在子组件内部添加一个侦听器:监听当前id的变化

created() {
    //加载部门负责人列表数据
    this.loadEmployeesSimples()
    //如果为编辑状态,获取部门详情
    if (this.isEdit) this.loadDepartDetail()
  },
watch: {
    id: function(newVal, oldVal) {
      //调用获取部门详情函数
      this.loadDepartDetail()
    }
  }, 
  //上面这种写法不会立即触发,还需在created()中调用一次,用下面这种方法就不需要在created()中调用了
  //watch: {
  //   id: {
  //     handler: function(newVal, oldVal) {
  //       this.loadDepartDetail()
  //     },
  //     immediate: true 
  //   }
  // },
  //immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即   //执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。所以当为     //true时 在created周期里就可以不用在写 已经在watch 中写过的方法了

但是这种方法在清空表单数据的时候会有一个bug,不推荐使用,后面会详细讲到.

解决方案五:给子组件添加key值

key就是给每一个vnode的唯一id,可以依靠key更准确地拿到oldVnode中对应的节点。

避免组件“原地复用”带来的副作用,加上key,可以让组件在数据变化时强制更新组件。

<el-dialog
        :title="isEdit?'编辑':'新增'"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        @close="resetForm"
      >
        <!-- 给子组件添加key值 -->
        <deptDialog
          :id="fatherId"
          :key="fatherId"
          :origin-list="originList"
          :is-edit="isEdit"
          @success="doSuccess"
          @doClose="dialogVisible=false"
        />
      </el-dialog>

问题二:添加表单中也会出现部门详情数据

还是上面说到的问题,关闭弹层时,子组件被没有销毁,它只是隐藏了,所以我们需要手动清除表单中的数据.

(方案一添加destroy-on-close属性,方案二v-if="dialogVisible",方案五给子组件添加key值,不会出现这个问题)

分析:有如下三个操作都需要我们去重置表单

  • 取消
  • 确定
  • 用户直接点击关闭

所以我们可以在Dialog的@close的回调中写一次代码就行了

父组件:

// 给父组件添加 @close="resetForm"
 <el-dialog
        :title="isEdit?'编辑':'新增'"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        @close="resetForm"
      >
      //给子组件添加  ref="deptDialog"
        <deptDialog
          v-if="dialogVisible"
          ref="deptDialog"
          :origin-list="originList"
          :is-edit="isEdit"
          @success="doSuccess"
          @doClose="dialogVisible=false"
        />
      </el-dialog>
// 重置子组件表单
    resetForm() {
      // 调用子组件中的重置表单方法
      this.$refs.deptDialog.resetForm()
    }

子组件:

// 在父组件中 dialog close时,来调用
    resetForm() {
      // resetFields是element-ui中的el-form组件提供一个api,它的作用是:
      // 1. 重置表单数据
      // 2. 清空校验结果(页面上红色的提示)
     this.$refs.deptForm.resetFields()
    }

清空表单数据的bug

问题重现

  • 选中a部门,进行编辑,故意让编辑出错,在表单上出现错误
  • 点击取消
  • 再次对a部门进行编辑,发现数据没有显示出来

原因分析

上面的操作中,前后两次编辑的是同一个部门,所以子组件内对id的watch并没有执行,导致内容为空

所以不推荐使用方案四,对id进行侦听

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue如何监听对象或者数组某个属性的变化详解

    vue如何监听对象或者数组某个属性的变化详解

    这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通过监听器函数接收新旧值,实现属性间的数据联动,需要的朋友可以参考下
    2024-12-12
  • 详解Vue 换肤方案验证

    详解Vue 换肤方案验证

    这篇文章主要介绍了Vue 换肤方案验证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Vue3项目页面实现echarts图表渐变色的动态配置的实现步骤

    Vue3项目页面实现echarts图表渐变色的动态配置的实现步骤

    在开发可配置业务平台时,需要实现让用户对项目内echarts图表的动态配置,让用户脱离代码也能实现简单的图表样式配置,颜色作为图表样式的重要组成部分,其配置方式是项目要解决的重点问题,所以本文介绍了Vue3项目页面实现echarts图表渐变色的动态配置
    2024-10-10
  • 你不可不知的Vue.js列表渲染详解

    你不可不知的Vue.js列表渲染详解

    这篇文章主要给大家介绍了关于你不可不知的Vue.js列表渲染的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Vue.js具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-10-10
  • vue-dplayer视频播放器组件的使用详解

    vue-dplayer视频播放器组件的使用详解

    Vue-DPlayer是一个易于使用、高性能的基于Vue.js的视频播放器组件,这篇文章将为大家详细介绍一下vue-dplayer视频播放器组件的安装与使用,需要的小伙伴可以参考下
    2023-09-09
  • vue 递归组件的简单使用示例

    vue 递归组件的简单使用示例

    这篇文章主要介绍了vue 递归组件的简单使用示例,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下
    2021-01-01
  • vue+iview框架实现左侧动态菜单功能的示例代码

    vue+iview框架实现左侧动态菜单功能的示例代码

    这篇文章主要介绍了vue+iview框架实现左侧动态菜单功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • vue+element开发使用el-select不能回显的处理方案

    vue+element开发使用el-select不能回显的处理方案

    这篇文章主要介绍了vue+element开发使用el-select不能回显的处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • vue使用laydate时间插件的方法

    vue使用laydate时间插件的方法

    这篇文章主要为大家详细介绍了vue使用laydate时间插件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Vue组件之全局组件与局部组件的使用详解

    Vue组件之全局组件与局部组件的使用详解

    本篇文章主要介绍了Vue组件之全局组件与局部组件的使用详解,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10

最新评论