ElDialog组件

el-dialog组件

问题描述

ElDialog 组件 closeOnClickModaltrue 时,鼠标不管在哪里按下在遮罩层抬起时或鼠标在遮罩层按下不管在哪里抬起时都会关闭遮罩层问题

解决方案

  1. 根目录node_moduleselement-uipackagesdialogsrccomponent.vue 复制全部代码

  2. 根目录srccomponents 下创建 ElseDialog 文件夹再创建 index.vue 文件

<template>
  <transition
    name="dialog-fade"
    @after-enter="afterEnter"
    @after-leave="afterLeave"
  >
    <!-- 此处将原来组件中的 @click 替换为 @mousedown 和 @mouseup,如此一来,在遮罩层中 mouseup 时也不会意外触发弹窗的关闭 -->
    <!-- 增加scrollbar类名所有弹窗出现滚动条而不是页面出现滚动条 -->
    <div
      v-show="visible"
      class="el-dialog__wrapper scrollbar"
      @mousedown="handleWrapperMousedown($event)"
      @mouseup="handleWrapperMouseup($event)"
    >
      <div
        role="dialog"
        :key="key"
        aria-modal="true"
        :aria-label="title || 'dialog'"
        :class="[
          'el-dialog',
          { 'is-fullscreen': fullscreen, 'el-dialog--center': center },
          customClass,
        ]"
        ref="dialog"
        :style="style"
      >
        <div class="el-dialog__header">
          <slot name="title">
            <span class="el-dialog__title">{{ title }}</span>
          </slot>
          <button
            type="button"
            class="el-dialog__headerbtn"
            aria-label="Close"
            v-if="showClose"
            @click="handleClose"
          >
            <i class="el-dialog__close el-icon el-icon-close"></i>
          </button>
        </div>
        <div class="el-dialog__body" v-if="rendered"><slot></slot></div>
        <div class="el-dialog__footer" v-if="$slots.footer">
          <slot name="footer"></slot>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
import Popup from "element-ui/src/utils/popup";
import Migrating from "element-ui/src/mixins/migrating";
import emitter from "element-ui/src/mixins/emitter";

export default {
  name: "ElseDialog",

  mixins: [Popup, emitter, Migrating],

  props: {
    title: {
      type: String,
      default: "",
    },

    modal: {
      type: Boolean,
      default: true,
    },

    modalAppendToBody: {
      type: Boolean,
      default: true,
    },

    appendToBody: {
      type: Boolean,
      default: false,
    },

    lockScroll: {
      type: Boolean,
      default: true,
    },

    closeOnClickModal: {
      type: Boolean,
      default: true,
    },

    closeOnPressEscape: {
      type: Boolean,
      default: true,
    },

    showClose: {
      type: Boolean,
      default: true,
    },

    width: String,

    fullscreen: Boolean,

    customClass: {
      type: String,
      default: "",
    },

    top: {
      type: String,
      default: "15vh",
    },
    beforeClose: Function,
    center: {
      type: Boolean,
      default: false,
    },

    destroyOnClose: Boolean,
  },

  data() {
    return {
      closed: false,
      mousedownClassBol: false,
      key: 0,
    };
  },

  watch: {
    visible(val) {
      if (val) {
        this.closed = false;
        this.$emit("open");
        this.$el.addEventListener("scroll", this.updatePopper);
        this.$nextTick(() => {
          this.$refs.dialog.scrollTop = 0;
        });
        if (this.appendToBody) {
          document.body.appendChild(this.$el);
        }
      } else {
        this.$el.removeEventListener("scroll", this.updatePopper);
        if (!this.closed) this.$emit("close");
        if (this.destroyOnClose) {
          this.$nextTick(() => {
            this.key++;
          });
        }
      }
    },
  },

  computed: {
    style() {
      let style = {};
      if (!this.fullscreen) {
        style.marginTop = this.top;
        if (this.width) {
          style.width = this.width;
        }
      }
      return style;
    },
  },

  methods: {
    getMigratingConfig() {
      return {
        props: {
          size: "size is removed.",
        },
      };
    },
    //增加对应事件
    handleWrapperMousedown(e) {
      this.mousedownClassBol =
        !!e.target.classList.contains("el-dialog__wrapper"); // 判断鼠标按下时是否在遮罩层上
    },
    handleWrapperMouseup(e) {
      if (
        !!e.target.classList.contains("el-dialog__wrapper") &&
        this.mousedownClassBol
      ) {
        // 判断抬起时是否在遮罩层上并且鼠标按下时也在遮罩层上都在时,触发handleWrapperClick事件
        this.mousedownClassBol = false;
        this.handleWrapperClick();
      }
    },
    handleWrapperClick() {
      if (!this.closeOnClickModal) return;
      this.handleClose();
    },
    handleClose() {
      if (typeof this.beforeClose === "function") {
        this.beforeClose(this.hide);
      } else {
        this.hide();
      }
    },
    hide(cancel) {
      if (cancel !== false) {
        this.$emit("update:visible", false);
        this.$emit("close");
        this.closed = true;
      }
    },
    updatePopper() {
      this.broadcast("ElSelectDropdown", "updatePopper");
      this.broadcast("ElDropdownMenu", "updatePopper");
    },
    afterEnter() {
      this.$emit("opened");
    },
    afterLeave() {
      this.$emit("closed");
    },
  },

  mounted() {
    if (this.visible) {
      this.rendered = true;
      this.open();
      if (this.appendToBody) {
        document.body.appendChild(this.$el);
      }
    }
  },

  destroyed() {
    // if appendToBody is true, remove DOM node after destroy
    if (this.appendToBody && this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el);
    }
  },
};
</script>
  1. 如果你是全局引入的element-ui 那么到 main.js 中添加如下代码
import Element from 'element-ui' // 全局引入element-ui
import ElseDialog from "@/components/ElseDialog"; // 自定义Dialog组件
// ...
Vue.use(Element, {
  size: Cookies.get('size') || 'medium' // set element-ui default size
})

// 全局替换 el-dialog
Vue.component('ElDialog', ElseDialog);
Vue 2.0
JSRUN前端笔记, 是针对前端工程师开放的一个笔记分享平台,是前端工程师记录重点、分享经验的一个笔记本。JSRUN前端采用的 MarkDown 语法 (极客专用语法), 这里属于IT工程师。