關於 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> 直接複製出來,再進行相應的一些小修改調整。
相關文章
- 關於elememt-ui中dialog彈窗多重巢狀的問題UI巢狀
- 關於頁面中彈窗的定位問題
- 關於layui的彈窗:一閃而過的問題UI
- van-dialog彈窗非同步關閉-校驗表單非同步
- layui使用彈出層 關閉後彈層的內容又顯示出來UI
- 關於彈出模態視窗的快取問題快取
- 頁面彈窗處理方案
- 關於彈窗的內部滑動穿透底層頁面的滑動的問題穿透
- 關於在request請求時,處理請求引數的問題
- win10系統怎麼關閉廣告彈窗 win10關閉惡意彈窗Win10
- win10彈窗熱點資訊怎麼關閉_win10熱點資訊彈窗的關閉方法Win10
- Antd的message.error 彈出的視窗不會關閉的問題Error
- 帶有半透明遮罩層可關閉視窗遮罩
- win10 彈窗廣告關閉方法 win10 彈出廣告怎麼關閉Win10
- 關閉網頁彈出提示視窗網頁
- sweetalert載入彈窗完成自動關閉
- win10怎麼關閉彈出警告_win10要如何關閉windows安全彈窗Win10Windows
- 點選彈出居中帶有透明遮罩層視窗遮罩
- 關閉網頁彈出是否關閉的提示網頁
- Vue+iview Modal元件關閉彈框之後報錯問題VueView元件
- element-ui的彈窗上使用btn會重新整理頁面UI
- js漸變彈出視窗和關閉視窗效果JS
- javascript點選彈出可以關閉帶有灰色背景彈出層JavaScript
- uniapp彈窗24小時之後彈APP
- 短視訊平臺搭建,收到通知後彈出相關提示的彈窗
- H5頁面遮罩彈框下層還能滾動的問題H5遮罩
- 如何實現在指定的時間後關閉視窗
- win10怎麼遮蔽彈出的廣告 win10關閉惡意彈窗Win10
- 封裝Vue Element的dialog彈窗元件封裝Vue元件
- 封裝React AntD的dialog彈窗元件封裝React元件
- 關於標題彈出指令
- 點選彈出帶有遮罩的視窗效果遮罩
- 在Watir中整合AutoIt處理JavaScript彈出視窗的方法JavaScript
- 彈出視窗螢幕(screen)實現關閉右上角的關閉按鈕事件(轉)事件
- 關於Jdon請求彈出新頁面的問題!!!
- 關閉 Chrome 瀏覽器時意外掛起的問題解決了!Chrome瀏覽器
- Qt 彈出的子頁面在未關閉的情況下,關閉主窗體,程式不退出的情況解決QT
- jQuery彈出帶有遮罩視窗效果jQuery遮罩