element--Diaolog弹窗打开之后渲染组件方式

lxf2023-05-05 12:57:01
摘要

这篇文章主要介绍了element--Diaolog弹窗打开之后渲染组件方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

目录
  • element--Diaolog弹窗打开之后渲染组件
    • 描述
    • 遇到的问题
  • Element组件的坑: 抽屉drawer和弹窗dialog
    • 业务场景
    • 针对第一个问题,具体解决方案如下
    • 针对第二个问题,具体解决方案如下
  • 总结

    element--Diaolog弹窗打开之后渲染组件

    描述

    父子两个组件,父组件打开子组件弹窗,然后执行方法请求接口,获取数据之后渲染页面,且每次点击都执行该方法。

    遇到的问题

    最开始简单地将方法放在子组件mounted里面,只有第一次打开弹窗会执行方法。

    了解到,弹窗只创建了一次。所以,在想是不是可以用keep-alive模式下的actived,然而并没有什么用。actived和deactived只在keep-alive使用时生效。

    然后想到在打开弹窗时候,强行调用子组件的方法

    // initFORM: 子组件方法
    // this.dialog.data.id: 子组件的请求接口的参数
    this.$refs.dialog.initForm(this.dialog.data.id)

    这次算是ok了,但是仅仅这样还不够。多次请求接口发现,如果接口请求速度够快,方法会提前执行,渲染组件。

    这本来不是什么坏事,坏就坏在渲染阶段。如果数据先一步到位,然后开始渲染组件,这时候弹窗还没有创建虚拟dom,会有bug。例如:我的弹窗如果是一个echart的图表,需要绑定一个dom节点进行渲染。节点都没有渲染出来,就会报错

    所以,第一次使用时候采用的方案:

    直接在调用子组件方法的外面包了一个setTimeout,让弹窗飞一会,然后再渲染。

    后面回过头看了一下,其实不用这么麻烦,element中弹窗组件有个回调函数

    element--Diaolog弹窗打开之后渲染组件方式

    选择opened

    <el-button @click="edit(id)">修改</el-button>
    <el-button @click="add">新增</el-button>
    <el-dialog
      :title="dialog.title"
      :visible.sync="dialog.visible"
      :width="dialog.width"
      center
      @opened="initForm"> <!-- element自带的弹窗打开回调函数 -->
      <component :is="dialog.name" ref="dialog"></component><!-- 动态组件:子组件 -->
    </el-dialog>
     
    <script>
    import { Add, Edit } from './Dialog'
    export default {
      components: {
        Add,
        Edit
      },
      data () {
        return {
          dialog: { // 弹窗组件传递数据
            title: '',
            visible: false,
            width: '',
            name: '' // 组件名
          }
        }
      },
      methods: {
        // 新增链接配置信息
        add () {
          this.dialog = {
            visible: true,
            title: '新增连接配置信息',
            width: '1000px',
            name: 'add-config'
          }
        },
        // 编辑修改设备信息
        edit (id) {
          this.dialog = {
            visible: true,
            title: '修改连接配置信息',
            width: '1000px',
            name: 'edit-config',
            data: id
          }
        },
        // 弹窗打开回调(更新数据)
        initForm () {
          switch (this.dialog.name) {
            case 'add':
              this.$refs.dialog.initForm()
              break
            case 'edit':
              this.$refs.dialog.initForm(this.dialog.data.id)
              break
            default:
              break
          }
        }
      }
    }
    </script>

    Element组件的坑: 抽屉drawer和弹窗dialog

    业务场景

    因为项目需要封装组件,考虑二次封装抽屉组件el-drawer,在父组件控制抽屉组件的显示隐藏。需要在指定的组件中打开抽屉。在抽屉组件el-drawer里使用自己封装的一个自定义组件。

    存在以下两个大问题:

    • 父组件控制抽屉组件的显示隐藏效果无法呈现
    • 抽屉组件里的自定义组件没有加载/创建出来

    针对第一个问题,具体解决方案如下

    父组件:

    <Drawer :isshowDrawer.sync = "isShowDrawer" @closeDrawer="isShowDrawer = $event"></Drawer>

    子组件Drawer:

     <el-drawer :visible.sync="isShow" direction="rtl" ref="drawerExam"></el-drawer>
     
     
    ...
     
        props: {
     
           isShowDrawer: {
              type: Boolean,
              default: false
           },
     
        },
     
        computed: {
            isShow: {
                set(val) {
                    this.$emit('closeDrawer', val);
                },
                get() {
                    return this.isShowDrawer;
                }
            },
        },
     
     

    若想实现,在指定的组件中打开抽屉,需要添加以下样式

    父组件样式:

    {
        position: relative;
        overflow: hidden;
    }

    抽屉组件:

    设置position为绝对定位,但是会出现一个问题:v-modal遮罩层是满屏显示的

    element--Diaolog弹窗打开之后渲染组件方式

     因此最终解决方案为:

    先在抽屉组件外套一层div标签,再修改内部样式

    <div class="drawerExam-container"> 
        <el-drawer :visible.sync="isShow" direction="rtl" ref="drawerExam" @open="openDrawer()"></el-drawer>
    </div>
     
    ...
     
     
    .drawerExam-container {
        ::v-deep .v-modal {
            position: absolute;
        }
    }

    针对第二个问题,具体解决方案如下

    在抽屉组件里,引入了自己封装的组件Checkbox,不能出现的原因是:Element官网有提到

    element--Diaolog弹窗打开之后渲染组件方式

    如下我在抽屉组件中引入了Checkbox(自己封装的组件),其中,dataList是父组件传给Checkbox的数据,chooseClass是Checkbox返回来的数据

     <el-drawer :visible.sync="isShow" direction="rtl" ref="drawerExam" @open="openDrawer()">
        <Checkbox :dataList="easy" @chooseEasy="updateForm" ref="easyRef"></Checkbox>
    </el-drawer>

    解决方法:

    给el-drawer增加open回调函数

    通过使用Checkbox内部方法赋值的方式,让Checkbox组件能够拥有值(因为在Checkbox组件内接收不到父组件传过去的dataList,才考虑使用Checkbox组件内部方法直接给组件赋值

    el-drawer的open回调函数:
    ...
            openDrawer() {
                this.$nextTick(() => {
                    setTimeout(() => {
                        this.$refs.easyRef.UpdateList(this.easy);
                    }, 0)
                })
     
            },
     
     
     
    Checkbox组件:
    ...
            UpdateList(arr) {
                this.newDataList = arr;
                // 置空该组件原有的值
                this.checkboxGroup = [];
                this.chooseEasy();
            },
     
            // 多选选中后给父组件传值
            chooseEasy() {
                this.$emit('chooseEasy', this.checkboxGroup);
            },

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。