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

Serafina ·
更新时间:2024-09-20
· 12 次阅读

目录

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中弹窗组件有个回调函数

选择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遮罩层是满屏显示的

 因此最终解决方案为:

先在抽屉组件外套一层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官网有提到

如下我在抽屉组件中引入了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); }, 总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持软件开发网。 



element

需要 登录 后方可回复, 如果你还没有账号请 注册新账号