Min

Min

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

前端機能ドラッグアンドドロップ:dragleaveドラッグイベントが子要素に透過する優雅な解決策

@[TOC](Table of Contents)

前情提要#

在这里插入图片描述
フロントエンドの作業中には、さまざまな技術に触れることが避けられません。ドラッグアンドドロップもその 1 つです。ドラッグアンドドロップに関する基本的な知識とデモは、ほとんどが MDN に詳しく記載されていますので、ここでは繰り返しません。代わりに、MDN の飛行機チケットを共有します。


アプリケーションシナリオ#

個々の人はさまざまなシナリオや要件に触れるかもしれませんが、それらはすべてこれらのイベントと API に基づいています。ここでは、時間を節約できるいくつかの価値のあるポイントを直接共有します。

⭐要素の位置をドラッグアンドドロップで変更する#

この機能にはいくつかのイベントが必要です。
1、dragstart
2、dragover //dragover はこのイベントでブラウザのデフォルト動作をキャンセルする必要があります。そうしないと、drop イベントが機能しません。
3、drop

// ステップ1:要素上のマウスオフセットを記録する
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)
}
// ステップ2:デフォルトの動作を阻止する
const handleDragOver = (event: DragEvent) => {
  // デフォルトの動作を阻止してドロップを許可する
  event.preventDefault()
}
// ステップ3:要素の位置を計算して割り当てる
const handleDrop = (event: any) => {
	// eventPosは要素を配置した後の正確な位置です
    eventPos = {
      x: event.offsetX - mouseOffsetMap.value.x,
      y: event.offsetY - mouseOffsetMap.value.y,
    }
    ...
    
  // デフォルトの動作を阻止する(一部の要素がリンクとして開かれる可能性があります)
  event.preventDefault()
}

⭐ドラッグアンドドロップでターゲット領域のスタイルを変更する#

2 つのイベントに基づいて、ターゲットの 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')
}

⭐子要素を貫通しないドラッグイベントのエレガントな解決策#

ターゲット領域の DOM 構造が複雑な場合、私の仕事のシナリオのように、次のような場合:
在这里插入图片描述
右側から左側のリストにドラッグアンドドロップし、左側の領域に入ると、領域に点線の枠を追加し、マウスが離れると点線の枠を解除したいと思います。しかし、ここで問題が発生します。領域に入ると、各子要素の領域が私に enter と leave を繰り返しトリガーします。点線の枠が点滅します。調査の結果、これはイベントのバブリングでもデフォルトの動作でもなく、このメソッドの特性によるものです。したがって、皆さんは別の方法を見つけるしかありません。何をするかはさまざまですが、私は以下の方法が最もエレガントだと考えています。主に 2 つのメソッドを利用します。
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')
  }
}

ここでは、カウンター変数を使用して、1 回のドラッグのロジックを理解するために出力しています。
在这里插入图片描述
2 回入るのは、最外部の領域に入ることが 1 回、子要素を通過することが 1 回だからです。子要素から離れると同様です。値が 0 であることを判断して、親要素の領域から離れることも合理的な方法です。他にも良い提案や意見があれば、議論や学習を歓迎します。

最後に#

📚 Vue コラム
☃️ プロフィール:技術が好きな人です。
🌞 モットー:地に足をつけて、謙虚に学ぶこと。
❗もし記事が役に立った場合は、可愛い小さな手でいいね👍とフォロー✅をしてください。私はすぐに返信しますので、さらなる交流をお楽しみください。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。