天天看點

elementUi el-dialog 對話框實作可拖拽、去掉覆寫層、并可操作底層的按鈕

一、對話框實作可拖拽功能

  • 實作方法:vue的指令
  • 使用方法:

1、将下列drag.js檔案放入代碼庫中;

2、在main.js中引入上述drag.js檔案;

3、在el-dialog元件中加上指令

<el-dialog
	v-dialogDrags
	:visible="dialogShow"
>
</el-dialog>
           

src/libs/drag.js

import Vue from 'vue';

/*

*  使用方法:

*  将以下代碼複制到一個js檔案中,然後在入口檔案main.js中import引入即可;

*  給elementUI的dialog上加上 v-dialogDrags

*  給dialog設定 :close-on-click-modal="false" , 禁止點選遮罩層關閉彈出層

*/

// 相容ie,谷歌
// v-dialogDrags: 彈窗拖拽屬性 (重點!!! 給模态框添加這個屬性模态框就能拖拽了)
Vue.directive('dialogDrags', { // 屬性名稱dialogDrags,前面加v- 使用
    bind(el, binding, vnode, oldVnode) {
        const dialogHeaderEl = el.querySelector('.el-dialog__header');
        const dragDom = el.querySelector('.el-dialog');
        dialogHeaderEl.style.cssText += ';cursor:move;';

        // 擷取原有屬性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
        const sty = (function () {
            if (window.document.currentStyle) {
                return (dom, attr) => dom.currentStyle[attr];
            } else {
                return (dom, attr) => getComputedStyle(dom, false)[attr];
            }
        })();

        dialogHeaderEl.onmousedown = (e) => {
            // 滑鼠按下,計算目前元素距離可視區的距離
            const disX = e.clientX - dialogHeaderEl.offsetLeft;
            const disY = e.clientY - dialogHeaderEl.offsetTop;

            const screenWidth = document.body.clientWidth; // body目前寬度
            const screenHeight = document.documentElement.clientHeight; // 可見區域高度(應為body高度,可某些環境下無法擷取)

            const dragDomWidth = dragDom.offsetWidth; // 對話框寬度
            const dragDomheight = dragDom.offsetHeight; // 對話框高度

            // 擷取到的值帶px 正則比對替換
            let styL = sty(dragDom, 'left');
            let styT = sty(dragDom, 'top');

            // 注意在ie中 第一次擷取到的值為元件自帶50% 移動之後指派為px
            if (styL.includes('%')) {
                styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
                styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
            } else {
                styL = +styL.replace(/\px/g, '');
                styT = +styT.replace(/\px/g, '');
            };

            document.onmousemove = function (e) {
                // 通過事件委托,計算移動的距離
                let left = e.clientX - disX + styL;
                let top = e.clientY - disY + styT;

                // 邊界處理
                if (left < 0) {
                    left = 0;
                }

                if (left > screenWidth - dragDomWidth) {
                    left = screenWidth - dragDomWidth;
                }

                if (top < 0) {
                    top = 0;
                }
                if (top > screenHeight - dragDomheight) {
                    top = screenHeight - dragDomheight;
                }

                // 移動目前元素
                dragDom.style.cssText += `;left:${left}px;top:${top}px;`;
            };

            document.onmouseup = function (e) {
                document.onmousemove = null;
                document.onmouseup = null;
            };
        };
    }
});
           

二、對話框去掉覆寫層可操作底層的按鈕功能

1、首先使用elementUi自帶的兩個參數

參數 說明 預設值
modal 是否需要遮罩層 true
close-on-click-modal 是否可以通過點選 modal 關閉 Dialog true
<el-dialog
	v-dialogDrags
	:visible="dialogShow"
	:modal="false"
	:close-on-click-modal="false"
>
</el-dialog>
           

這樣操作後發現灰色的遮罩層确實去掉了,但是通過審查元素檢視還是有一層透明的覆寫層的,而且這時候也無法點選底部的按鈕;

2、使用css3屬性 pointer-events

pointer-events:none

元素永遠不會成為滑鼠事件的target。但是,當其後代元素的pointer-events屬性指定其他值時,滑鼠事件可以指向後代元素,在這種情況下,滑鼠事件将在捕獲或冒泡階段觸發父元素的事件偵聽器。

簡單的說就是點選事件可以穿透本元素,作用于下層的元素;

pointer-events:auto

與pointer-events屬性未指定時的表現效果相同

// 覆寫層元素增加可穿透點選事件
.el-dialog__wrapper
    pointer-events:none;
// 彈窗層元素不可穿透點選事件(不影響彈窗層元素的點選事件)
.el-dialog
    pointer-events:auto;