work-notes(12):如何二次封装 Element UI 的 dialog 弹窗,发现弹窗只能点击触发一次是什么原因,如何解决弹窗只能触发一次的问题?

时间:2022-05-15

问题描述

前些天,公司要求制作一个私库,并且是在 element UI 的组件上进行二次封装,所以引生出一些问题,作为记录;

(1)如何进行二次封装 element UI 的 dialog 弹窗?

(2)弹窗为什么只能点击触发一次,第二次之后都没有反应?
	原因是,你没有传入一个 close 事件;
	1)当你第一次点击时,子组件里面的 visible 可视变成了 true,你点击关闭的时候,
	2)没有传入 close 事件,导致你 子组件里面的 visible 还是 true,所以点击没反应;

问题分析

1、如何二次封装 element UI 的 dialog 弹窗?

(1)首先可以确定,类似于封装成一个子组件,然后把对应的 宽等值 传入即可;

(2)把传入的值,绑定到子组件的标签上;

2、实现过程

(1)在 script 标签 中 props 传入值
 props: {
   //  是否可视
   isVisible: {
     type: Boolean,
     required: true,
   },
   //  弹窗宽度,百分比。默认50%
   dialogWidth: {
     type: [Number, String],
     default: "50%",
   },
   //  是否展现关闭按钮
   showClose: {
     type: [Number, String],
   },
   // apend-to-body 值,用于嵌套弹窗
   apendToBody: {
     type: Boolean,
   },
   // 头部 title 背景图宽度
   titleBackgroundWidth: {
     type: [Number, String],
     default: "320",
   },
   // title 名称
   titleText: {
     type: String,
     required: true,
   },
   // pop_img 头部背景图片颜色,当为 true 时为深暗色,为 false 时为 浅色;
   popImgColor: {
     type: [Boolean, String],
   },
 },
(2)绑定到 dialog 标签内
主要我这里是用那个自定义 dialog;
主要结构:
<el-dialog>
	// 头部标题
	<template #title> </template>
	// 身体
	<template #default> </template>
 </el-dialog>
个人例子:
<template>
  <el-dialog
    class="dialog_box"
    top="5vh"
    :destroy-on-close="true"
    close-on-press-escape
    v-model="isVisible"
    :width="dialogWidth"
    :show-close="showClose"
    :append-to-body="apendToBody"
    :before-close="onClose"
  >
    <!-- 头部 -->
    <template #title>
      <div
        class="dialog_title"
        :style="{ width: titleBackgroundWidth + 'px' }"
        :class="[popImgColor === 'true' ? 'pop_img_color' : '']"
      >
        <span>{{ titleText }}</span>
      </div>
    </template>

    <!-- 身体 -->
    <template #default>
      <!-- 作为插槽,引入其他组件的 body 部分 -->
      <slot></slot>
    </template>
  </el-dialog>
</template>
解释
(1)在 dialog 标签下的 是默认 element UI 的值;传入值可以直接绑定进去;
(2)其他 div 就是自己写的;
	绑定方式可以绑定在 class(:class) 、style(:style);

绑定 class style 的写法详细,这是我之前写的博客

3、弹窗为什么只能点击触发一次,第二次之后都没有反应?

上面已经描述了为什么第二次之后没有反应的原因;
下面就讲方向;

(1)在调用的页面传入一个 close 函数;

(2)在子组件内部进行绑定,绑定位置很特别,而且思维也很灵巧;

4、实现过程

(1)在调用的页面写一个 close 函数传入;

close方法很简单,就把传入的值 visible 变成 false;

// 关闭弹窗方法
dialogClose() {
  this.visible = false;
},
个人例子
(1)传入的 方法绑定到 @on-close="dialogClose";
<template>
  <div v-if="visible">
    <!-- 实际 弹窗组件 标签 -->
    <zwcom-dialog
      :isVisible="visible"
      @on-close="dialogClose"
    >
      <div>弹窗体内容,身体默认由内容撑开</div>
    </zwcom-dialog>
  </div>
</template>


<script>
export default {
  data() {
    return {
      visible: false,
    };
  },
  methods: {
    // 关闭弹窗方法
    dialogClose() {
      this.visible = false;
    },
  },
};
</script>
(2)在子组件内部进行绑定
这里我就删除过多的内容,仅保留例子内容;

(1)内部就是 emits 接受,但是我这里写在 methods 里面用方法进行调用;【巧妙1】
(2)再把这个方法,绑定在element UI 的 dialog 标签的 before-close 事件里;【巧妙2】

解释:
1)父组件传进来的函数绑定到函数里面,这样简单易懂;
2)绑定到 before-close;
	①原本 before-close 用法是,当弹窗点击蒙版自动关闭时,弹出弹窗需要二次确认关闭;
		这里直接调用父组件的函数,直接把 visivle = false;就可以实现关闭,这就是巧妙之处;
具体内部调用
 methods: {
  //关闭弹框
   onClose() {
     this.$emit("on-close");
   },
 },
个人例子
<template>
  <el-dialog  
    v-model="isVisible"
    :before-close="onClose"
   >
    <!-- 头部 -->
    <template #title> </template>

    <!-- 身体 -->
    <template #default>
      <!-- 作为插槽,引入其他组件的 body 部分 -->
      <slot></slot>
    </template>
  </el-dialog>
</template>

<script>
export default {
  name: "zwcom-dialog",
  data() {
    return {};
  },
  props: {
    //  是否可视
    isVisible: {
      type: Boolean,
      required: true,
    },
  },
  emits: [],
  methods: {
    //关闭弹框
    onClose() {
      this.$emit("on-close");
    },
  },
  watch: {},
};
</script>
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值