解決VUE自定義拖拽指令時 onmouseup 與 click事件衝突
阿新 • • 發佈:2019-01-12
功能描述:
如圖,右側懸浮選單按鈕,只支援上下方向拖動,點選時展開或關閉選單。
BUG說明:
滑鼠上下方向拖拽,如果鬆開時滑鼠位於懸浮按鈕上會預設執行click事件,經驗證,click事件與mouse事件的執行順序為onmousedown =》onmouseup =》onclick,意味著在click事件執行時會與與其相關的mouse事件衝突。
解決方案:
因為click事件執行時間短,所以利用滑鼠拖動的時間差作為標誌,在拖拽事件中計算滑鼠從onmousedown 到onmouseup 所用的時間差,與200ms作比較,作為全域性變數。由於vue的directives自定義指令中無法使用this,所以個人採用給元素設定屬性的方式來解決全域性變數的儲存問題。
1、自定義上下拖拽指令
說明:指令中沒有this關鍵字,指令中通過el可以直接拿到指令繫結的元素;
directives: { drag: { // 指令的定義 bind: function (el) { let odiv = el; //獲取當前元素 let firstTime='',lastTime=''; odiv.onmousedown = (e) => { document.getElementById('dragbtn').setAttribute('data-flag',false) firstTime = new Date().getTime(); // 算出滑鼠相對元素的位置 let disY = e.clientY - odiv.offsetTop; document.onmousemove = (e) => { // 用滑鼠的位置減去滑鼠相對元素的位置,得到元素的位置 let top = e.clientY - disY; // 頁面範圍內移動元素 if (top > 0 && top < document.body.clientHeight - 48) { odiv.style.top = top + 'px'; } }; document.onmouseup = (e) => { document.onmousemove = null; document.onmouseup = null; // onmouseup 時的時間,並計算差值 lastTime = new Date().getTime(); if( (lastTime - firstTime) < 200){ document.getElementById('dragbtn').setAttribute('data-flag',true) } }; }; } } },
2、懸浮選單點選事件中進行驗證。
click(e) { // 驗證是否為點選事件,是則繼續執行click事件,否則不執行 let isClick = document.getElementById('dragbtn').getAttribute('data-flag'); if(isClick !== 'true') { return false } if (!localStorage.settings) { return this.$message.error('請選擇必填項並儲存'); } if (this.right === -300) { this.right = 0; this.isMask = true; } else { this.right = -300; this.isMask = false; } },
參考:
1、基於Vue實現拖拽效果;
2、javascript事件, 解決mousedown和click衝突事件, 滑鼠事件, 鍵盤事件, 文字事件用法簡介;