關於 Element-ui Dialog 引用時,在彈窗上 mousedown 後再在遮罩層 mouseup 引發的意外彈窗關閉問題的處理方案
問題:
Element-UI 作為當前較為成熟的 Vue 框架的 UI 元件,能有效的提高特異性不強的專案的介面開發。但是,作為一個要兼備處理多方面問題的第三方庫,Element-UI 也存在著一些問題。比如 <el-dialog>。
在引用 <el-dialog> 時,尤其是將其作為編輯彈窗時,常常會有一個問題,便是在使用滑鼠滑動選取彈窗中做文字選擇時,若不注意將游標滑到彈窗窗體之外的遮罩層處,此時鬆開滑鼠,就會導致彈窗被關閉掉的現象,十分影響使用體驗。
當然,這種情況也有一個折衷的方案,那就是通過官方開放的介面 close-on-click-modal 設定為 false。但是,這顯然並不完全符合我們的目的,我們要的是保留點選遮罩層的時候,能夠關閉彈窗,同時的,當我們在使用滑鼠選取彈窗內文字時,即便游標不慎滑到談窗外也不會觸發彈窗的關閉。
查詢所得相關方案:
[vue][element-ui]mousedown在Dialog上 mouseup在遮罩上時自動關閉彈窗的問題總結——丹哥不是哥
仍存在問題:
按查詢所得的方案,及通過修改 element-ui 的庫來實現。但是,這種方式存在一個問題,那就是修改後的 element-ui 庫需要作為靜態資源儲存在專案中,並且要提交到團隊的程式碼倉庫中,其他成員使用時也必須同步修改後的 element-ui 庫。
這樣的做法並不符合現下的開發模式和庫的引用方式。
最終決定方案:
建立新的元件,將 element-ui 的 <el-dialog> 複製出來後,對其再進行修改,然後作為自己的自定義元件來使用。如下:
<template>
<transition
name="dialog-fade"
@after-enter="afterEnter"
@after-leave="afterLeave">
<div
v-show="visible"
class="el-dialog__wrapper else close-on-mousedown"
<!-- 此處,新增了兩個類名,作為除錯時的識別 -->
@mousedown.self="handleWrapperClick">
<!-- 此處將原來元件中的 @click 替換為 @mousedown,如此一來,在遮罩層中 mouseup 時也不會意外觸發彈窗的關閉 -->
<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,
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.'
}
};
},
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>
以上的元件,事實上就是將 element-ui 的 <el-dialog> 直接複製出來,再進行相應的一些小修改調整。
相關文章
- van-dialog彈窗非同步關閉-校驗表單非同步
- 關於layui的彈窗:一閃而過的問題UI
- 關於彈窗的內部滑動穿透底層頁面的滑動的問題穿透
- Antd的message.error 彈出的視窗不會關閉的問題Error
- 關於在request請求時,處理請求引數的問題
- 帶有半透明遮罩層可關閉視窗遮罩
- win10系統怎麼關閉廣告彈窗 win10關閉惡意彈窗Win10
- win10彈窗熱點資訊怎麼關閉_win10熱點資訊彈窗的關閉方法Win10
- sweetalert載入彈窗完成自動關閉
- win10怎麼關閉彈出警告_win10要如何關閉windows安全彈窗Win10Windows
- win10 彈窗廣告關閉方法 win10 彈出廣告怎麼關閉Win10
- 關閉網頁彈出是否關閉的提示網頁
- 封裝React AntD的dialog彈窗元件封裝React元件
- 封裝Vue Element的dialog彈窗元件封裝Vue元件
- Vue+iview Modal元件關閉彈框之後報錯問題VueView元件
- 倒數計時5S秒自動關閉彈窗
- uniapp彈窗24小時之後彈APP
- 從底部彈出Dialog視窗
- 短視訊平臺搭建,收到通知後彈出相關提示的彈窗
- 你可能不知道的dialog彈窗
- win10怎麼遮蔽彈出的廣告 win10關閉惡意彈窗Win10
- 關於標題彈出指令
- Qt 彈出的子頁面在未關閉的情況下,關閉主窗體,程式不退出的情況解決QT
- 關閉 Chrome 瀏覽器時意外掛起的問題解決了!Chrome瀏覽器
- element UI Popover 彈出框裡一帶有下拉屬性觸發彈窗進行關閉以及位置偏移的情況問題解決方法UI
- Winform MessageBox訊息彈窗如何實現自動關閉ORM
- win10系統老是彈出可選功能怎樣關閉_win10總彈出可選功能視窗的關閉教程Win10
- 【單頁應用】我們該如何處理框架彈出層層級關係?框架
- WPF App後臺檔案彈窗導致奇怪的問題APP
- 關於時間 PHP 處理包遇到的問題時間序列化差值問題PHP
- 0x02. 處理視窗關閉
- Element修改彈窗類元件的層級元件
- win10提示怎麼關_win10關閉開啟軟體提示彈窗的方法Win10
- 解決element---el-dialog--關閉報錯問題
- Android之Window和彈窗問題Android
- 彈出層layer 完整步驟以及在編寫彈出層時遇到的錯誤
- win10系統下怎麼關閉windows defender阻止彈窗Win10Windows
- 關於驅動在何處上拉的問題