Min

Min

持续投身前端开发领域,一起分享,交流,成长

前端功能拖曳篇:dragleave拖曳事件穿透子元素的優雅解決方案

@TOC

前情提要#

在這裡插入圖片描述
在前端工作過程中,避免不了要接觸各種技術,拖拽就是其中一個,大部分關於拖拽的基礎知識和 Demo 都在 MDN 中寫的很詳細的,這裡便不再贅述,給大家分享一個MDN 飛機票


應用場景#

每個人會接觸不同的場景和需求,但是底層都是基於這些事件及 API 的,那我就直接分享幾個有價值的點,可以節省大家的時間。

⭐拖拽改變元素位置#

這個功能要依據幾個事件
1、dragstart
2、dragover //dragover 必須要在此事件中取消瀏覽器的默認行為,否則 drop 事件不會生效
3、drop

// 第一步,記錄鼠標指針在元素上的偏移量
const rightItemDragStart = (event: any) => {
  // 記錄初始鼠標偏移量
  mouseOffsetMap.value = { x: event.offsetX, y: event.offsetY }
  // 傳遞拖拽元素id
  event.dataTransfer.setData('text/plain', event.target.id)
  event.dataTransfer.setData('rightDrag', true)
}
// 第二步 設置阻止默認行為
const handleDragOver = (event: DragEvent) => {
  // 阻止默認行為以允許放置
  event.preventDefault()
}
// 第三步 計算元素位置賦值
const handleDrop = (event: any) => {
	// eventPos 這個位置就是元素放置後的準確位置
    eventPos = {
      x: event.offsetX - mouseOffsetMap.value.x,
      y: event.offsetY - mouseOffsetMap.value.y,
    }
    ...
    
  // 阻止默認行為(會作為某些元素的鏈接打開)
  event.preventDefault()
}

⭐拖拽改變目標區域的樣式#

依據倆個事件,要綁定給目標 Dom
1、dragenter
2、dragleave

/**
 * 處理拖拽進入事件
 *
 * @param event 拖拽事件對象
 */
const handleDragEnter = (event: any) => {
  rightWrapRef.value?.classList.add('out-line')
}
/**
 * 當拖拽元素離開目標區域時觸發
 *
 * @param event 拖拽事件對象
 */
const handleDragLeave = (event: DragEvent) => {
  rightWrapRef.value?.classList.remove('out-line')
}

⭐dragleave 拖拽事件穿透子元素的優雅解決方案#

如果目標區域的 dom 結構比較複雜,比如我在工作中的場景這樣:
在這裡插入圖片描述
我想從右側往左側的列表裡拖拽,並且在進入左側區域的時候,為區域增加一個虛線框,鼠標離開的時候取消虛線框。但此時問題出現了,在我拖拽進入區域後,每一個子元素的區域都會致使我重複觸發 enter,leave, 導致虛線框閃爍,在一番調研後發現確實有這個問題,它不是事件的冒泡,也不是默認行為,而是改方法的特性導致的,所以大家只好另闢蹊徑,怎麼做的都有,但我認為最優雅的是下面這種。主要利用倆個方法
1、handleLeftDragEnter
2、handleLeftDragLeave

const draggingCounter = ref(0)
const handleLeftDragEnter = (event: any) => {
   draggingCounter.value++
  // 左側元素放入左側區域不處理
  leftWrapRef.value?.classList.add('out-line')
}
const handleLeftDragLeave = (event: any) => {
  draggingCounter.value--
  if(draggingCounter.value === 0) {
     leftWrapRef.value?.classList.remove('out-line')
  }
}

這裡利用一個計數變量,大家看我打印這個一次拖拽的邏輯就很好理解了
在這裡插入圖片描述
倆次進入元素是因為進入最外部區域算一次,途徑子元素算一次,離開子元素也是同理,我們通過判斷數值為 0 來推導離開父元素的區域也是很合理的做法。大家如果還有什麼好的建議和觀點歡迎討論學習。

最後#

📚 vue 專欄
☃️ 個人簡介:一個喜愛技術的人。
🌞 勵志格言:腳踏實地,虛心學習。
❗如果文章還可以,記得用你可愛的小手點贊👍關注✅,我會在第一時間回、回訪,歡迎進一步交流。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。