序文ソースコードは合計で 100 行強しかありません。これを読めば、react-dnd などの成熟した react ドラッグ ライブラリの実装アイデアを大まかに理解でき、これらのライブラリをすぐに使い始めることができます。 フックを使用した場合の一般的な効果は次のとおりです。 私たちの目標は、useDrag フックと useDrop フックを実装することです。これにより、要素を簡単にドラッグ可能にすることができ、以下に示すように、ドラッグの各ライフサイクルでメッセージの配信をカスタマイズできます (ちなみに、ドラッグによってトリガーされるいくつかのイベントを導入します)。
使い方+ソースコード解説 クラスHelloはReact.Component<any, any>を拡張します。 コンストラクタ(props: any) { スーパー(小道具) this.state = {} } 与える() { 戻る ( <ドラッグアンドドロップ> <ドラッグ要素 /> <ドロップ要素 /> </ドラッグアンドドロップ> ) } } ReactDOM.render(<Hello />, window.document.getElementById("root")) 前述の通り、DragAndDrop コンポーネントの機能は、現在ドラッグされている要素がどの DOM であるかなどのメッセージを、useDrag と useDrop を使用するすべてのコンポーネントに渡すことですが、必要に応じて他の情報を追加することもできます。その実装を見てみましょう。 DragAndDropManager を React.createContext に追加します。 const DragAndDrop = ({ children }) => ( <DragAndDropContext.Provider 値 = {{ DragAndDropManager: new DragAndDropManager() }}> {子供たち} </ドラッグアンドドロップコンテキスト.プロバイダー> ) メッセージパッシングは react の Context API を使用して実装されていることがわかります。この DragAndDropManager に注目してください。実装を見てみましょう。 デフォルトクラスDragAndDropManagerをエクスポートします。 コンストラクタ() { this.active = null this.subscriptions = [] this.id = -1 } setActive(アクティブプロパティ) { this.active = アクティブプロパティ this.subscriptions.forEach((サブスクリプション) => subscription.callback()) } subscribe(コールバック) { this.id += 1 this.subscriptions.push({ 折り返し電話、 id: this.id, }) this.idを返す } 登録解除(id) { this.subscriptions = this.subscriptions.filter((sub) => sub.id !== id) } } setActive の機能は、現在ドラッグされている要素を記録することです。これは useDrag で使用されます。useDrag のフックの実装を見ると、setActive メソッドを呼び出してドラッグされた DOM 要素を渡すだけで、現在ドラッグされている要素がわかることがわかります。 さらに、イベントをサブスクライブするための API subscribe も追加しました。まだ使用していないため、この例では無視してかまいません。サブスクリプション イベントを追加できることだけ知っておいてください。 次に、useDrag の使い方を見てみましょう。DragElement の実装は次のとおりです。 関数DragElement() { 定数入力 = useRef(null) const hanleDrag = useDrag({ 参照: 入力、 collection: {}, // ここでドロップ要素に渡したいメッセージを入力できます。このメッセージは後でドロップ要素にパラメータとして渡されます}) 戻る ( <div ref={入力}> <h1 role="button" onClick={handleDrag}> ドラッグ要素 </div> ) } 非常にシンプルなuseDragの実装を見てみましょう。 デフォルト関数 useDrag(props) をエクスポートします。 const { DragAndDropManager } = useContext(DragAndDropContext) 定数handleDragStart = (e) => { DragAndDropManager.setActive(props.collection) e.dataTransfer !== 未定義の場合 { e.dataTransfer.effectAllowed = "移動" e.dataTransfer.dropEffect = "移動" e.dataTransfer.setData("text/plain", "drag") // Firefox の修正 } (props.onDragStart)の場合{ props.onDragStart(DragAndDropManager.active) } } 使用効果(() => { もしprops.refがそうであれば、戻り値は()=>{} 定数{ 参照: { 現在の }, } = 小道具 if (現在) { current.setAttribute("ドラッグ可能", true) current.addEventListener("dragstart", handleDragStart) } 戻り値 () => { current.removeEventListener("dragstart", handleDragStart) } }, [props.ref.current]) handleDragStart を返す } useDrag が行うことは非常にシンプルです。
このうち、useDrop の使用と DropElement の実装は次のとおりです。 関数 DropElement(props: any): any { 定数入力 = useRef(null) ドロップを使用します({ 参照: 入力、 // e は、dragOver イベントが発生したときにドラッグされている要素のイベント オブジェクトを表します // collection はストアに保存されているデータです // showAfter は、マウスが要素をドラッグしているときに、ドロップされた要素の上をマウスが通過するかどうかを示します (上は上半分、下は下半分) onDragOver: (e, コレクション, showAfter) => { // 上半分を通過すると、ドロップ要素の上部の境界線が赤くなります if (!showAfter) { input.current.style = "border-bottom: none;border-top: 1px の赤一色" } それ以外 { // 下半分を通過すると、ドロップ要素の上部の境界線は赤になります input.current.style = "border-top: none; border-bottom: 1px solid red" } }, // ドロップ要素上でマウスを離すと、スタイルがクリアされます onDrop: () => { 入力.現在のスタイル = "" }, // ドロップ要素を離れるとスタイルはクリアされます onDragLeave: () => { 入力.現在のスタイル = "" }, }) 戻る ( <div> <h1 ref={input}>要素をドロップ</h1> </div> ) } 最後に、useDropの実装を見てみましょう。 デフォルト関数 useDrop(props) をエクスポートします。 // 最も外側のストアのデータを取得します。const { DragAndDropManager } = useContext(DragAndDropContext) 定数handleDragOver = (e) => { // e はドラッグ イベント オブジェクトです e.preventDefault() // 下の getBoundingClientRect の図を参照してください const overElementHeight = e.currentTarget.getBoundingClientRect().height / 2 定数 overElementTopOffset = e.currentTarget.getBoundingClientRect().top // clientYはマウスからブラウザページの表示領域の上部までの距離です。const mousePositionY = e.clientY // mousePositionY - overElementTopOffset は、要素内のマウスから要素の border-top までの距離です。const showAfter = mousePositionY - overElementTopOffset > overElementHeight (props.onDragOver)の場合{ props.onDragOver(e, DragAndDropManager.active, showAfter) } } // ドロップイベント const handledDop = (e: React.DragEvent) => { e.preventDefault() (props.onDrop)の場合{ props.onDrop(DragAndDropManager.active) } } // dragLeave イベント const handlerragLeave = (e: React.DragEvent) => { e.preventDefault() (props.onDragLeave)の場合{ props.onDragLeave(DragAndDropManager.active) } } // イベントを登録します。メモリリークを避けるために、コンポーネントを破棄するときにはイベントの登録を解除する必要があることに注意してください。useEffect(() => { もしprops.refがそうであれば、戻り値は()=>{} 定数{ 参照: { 現在の }, } = 小道具 if (現在) { current.addEventListener("dragover", handleDragOver) current.addEventListener("ドロップ"、handledDop) current.addEventListener("dragleave", 処理済みragLeave) } 戻り値 () => { current.removeEventListener("dragover", handleDragOver) current.removeEventListener("drop", 処理されたDop) current.removeEventListener("dragleave", 処理済みragLeave) } }, [props.ref.current]) } GetBoundingClientRect API ダイアグラム: rectObject = object.getBoundingClientRect(); rectObject.top: 要素の上端からウィンドウの上端までの距離。 rectObject.right: 要素の右側からウィンドウの左側までの距離。 rectObject.bottom: 要素の下部からウィンドウの上部までの距離。 rectObject.left: 要素の左側からウィンドウの左側までの距離。 これで、100 行を超えるコードで React ドラッグ アンド ドロップ フックを実装する方法に関するこの記事は終了です。React ドラッグ アンド ドロップ フックに関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: mysql5.7 でユーザーの初期パスワードを変更する方法
>>: Linux カーネル デバイス ドライバー システム コールに関する注意事項
MySQL マルチテーブルクエリ (直積原理)まず、データが使用するテーブルを決定します。デカルト...
最近、データライフサイクル管理の詳細を整理していたときに、小さな問題を発見しました。それは、MySQ...
dockerでイメージを削除するコマンドはdocker rmiですが、このコマンドを実行してもイメー...
アプリケーションシナリオ多くの場合、Linux サーバーに tomcat や nginx などのソフ...
新しい設定ファイルを作成します (たとえば、nginx インストール ディレクトリの下の conf ...
目次序文1. ロックとは何ですか? 2. InnoDBストレージエンジンのロック2.1 ロックの種類...
この axios パッケージは、vue3 デモで使用されます。便宜上、element-plus は ...
CMakeをインストール sudo apt をインストール cmake この方法はインストールが簡単...
目次1. 画像を取得する2. ブローカーサーバーを作成する3. ブローカーを作成する4. Rocke...
1. テーブルAのデータを使用してMySQLのテーブルBの内容を更新するたとえば、データ テーブル内...
Centos にプロジェクトをデプロイするときに奇妙な問題が見つかりました。データベース接続で例外...
序文レイアウトの点では、Gobang はランダムな動きを目的とするゲームよりも実装がはるかに簡単で、...
イメージをダウンロードします(オプションの手順です。省略した場合は、手順 3 と 4 で自動的にイン...
Docker イメージの最初の行は FROM alpine などのイメージで始まりますが、最初のベー...
目次1. 初期化構造2. 蛇の色のレンダリング3. ヘビの動き4. ヘビの死を判定する方法 ヘビの死...