Vueカスタムディレクティブを使用してドラッグアンドドロッププラグインを構築する方法

Vueカスタムディレクティブを使用してドラッグアンドドロッププラグインを構築する方法

HTML5 のドラッグ アンド ドロップ機能は誰もが知っていますが、これを使用するとドラッグ アンド ドロップ機能を簡単に実装できます。たとえば、一部の選択操作のシナリオでは、マウスでクリックするよりもドラッグの方がユーザーにとって受け入れやすく、理解しやすいです。今日はこの機能を使用し、それを Vue のカスタム命令と組み合わせて、シンプルでありながら実用的なドラッグ アンド ドロップ プラグインを実装します。

なぜプラグインと呼ばれるのでしょうか?私たちの目標は Vue コンポーネントを開発することではなく、2 つの Vue カスタム命令を開発することであり、最終的にはこれら 2 つのカスタム命令が ES6 クラスにカプセル化され、実際のプロジェクトに導入するときに簡単に使用できるようになります。

ほとんどのドラッグ アンド ドロップ シナリオでは、選択した要素を領域 A から領域 B にドラッグ アンド ドロップします。ここでは 2 つの概念が関係しています。1 つはドラッグ可能、もう 1 つは配置可能という概念です。選択した要素はドラッグ可能で、ターゲット領域 (コンテナー) は配置可能である必要があります。

ドラッグ可能な vue コンポーネントを開発する場合、またはドロップ可能なコンポーネントを開発する場合、ドラッグ アンド ドロップできるのはこのコンポーネントのみです。この時点で、要件が変更され、別のコンポーネントでドラッグ アンド ドロップをサポートする必要がある場合は、他のコンポーネントのドラッグ アンド ドロップ コードを記述する必要があります。あるいは、他のプロジェクトでもドラッグ アンド ドロップ機能が必要になり、それを再開発する必要があるかもしれません。これはメンテナンスや再利用に役立ちませんが、Vue のカスタム命令はこの問題をうまく解決するのに役立ちます。このコンポーネント (要素) をドラッグ アンド ドロップ可能にするには、コンポーネント (通常の DOM 要素を含む) にカスタム命令を追加するだけで、柔軟に使用できるようになります。

コア機能のデフォルトの組み込みディレクティブ (v-model および v-show) に加えて、Vue ではカスタム ディレクティブを登録することもできます。 Vue 2.0 では、コードの再利用と抽象化の主な形式はコンポーネントであることに注意してください。ただし、場合によっては、通常の DOM 要素に対して低レベルの操作を実行する必要があり、このような場合はカスタム命令が使用されます。

要約すると、この記事の目標は、次の 2 つのカスタム手順を完了することです。

  • v-dragはコンポーネントをドラッグ可能にする
  • v-dropはコンポーネントをドロップ可能にする

目標は明確です。さあ始めましょう!これら 2 つの命令をどのコンポーネントでも機能させるには、Vue グローバル ディレクティブを登録する必要があります。

Vue.directive('ドラッグ', {
   bind(el, バインディング, vnode){
        // ディレクティブが最初に要素にバインドされたときに 1 回だけ呼び出されます。
        //ここで、1 回限りの初期化セットアップを実行できます。
    }
})
Vue.directive('drop', {
   bind(el, バインディング, vnode){
        //
    }
})

プロジェクトが vue-cli を使用してビルドされている場合は、main.js の vue 初期化の上にこのコードを記述できます。

まず、ドラッグ ディレクティブの bind フックにコードを記述します。bind は 1 回だけ呼び出され、ディレクティブが最初に要素にバインドされるときに呼び出されるため、bind フックを使用します。このディレクティブの目的は、コンポーネント(要素)をドラッグ可能にすることなので、elのdraggableをtrueに設定します。

el.draggable = true;
el.ondragstart = (イベント)=>{
  event.dataTransfer.setData("Text", "あなたのデータ...");
}

要素がドラッグされると、まず ondragstart イベントがトリガーされます。通常、このイベントでイベントの dataTransfer のドラッグ データを設定します。その目的は、要素がドロップされたときに、ターゲット コンテナーがドラッグされたデータを取得できるようにすることです。ドラッグ アンド ドロップでデータを転送できない場合は意味がありません。上記のコードは、ドラッグ データを設定するために dataTransfer の setData メソッドを呼び出します。setData のパラメーター 1 はデータの種類を示し、パラメーター 2 は転送されるデータを示します。

残念ながら、ドラッグデータは現在文字列のみをサポートしています。複雑なオブジェクトを渡したい場合は、データをシリアル化することができます。

次に、ドロップ ディレクティブのバインド フックのコードを記述します。このディレクティブの目的は、コンポーネント (要素) をドロップ可能にすることなので、要素の ondragover (ドラッグ オーバー イベント) と ondrop (ドロップ イベント) のハンドラーを記述する必要があります。これら 2 つのハンドラーは、イベントのデフォルトの動作を防ぐ必要があります。

el.ondragover = (イベント)=>{
  event.preventDefault(); //デフォルトの動作を防止する}
el.ondrop = (イベント)=>{
  イベントをデフォルトにしない();
  let dragData = event.dataTransfer.getData('Text'); //ドラッグデータを取得する}

ドラッグ開始イベントで設定されたドラッグ データは、event.dataTransfer の getData メソッドを通じて取得できます。

これで、これらの 2 つの命令を任意のコンポーネントに追加できます。v-drag を持つコンポーネントはドラッグでき、v-drop を持つコンポーネントは配置してドラッグ データを受け取ることができます。

<MyComponent を v-drag></MyComponent>

<MyContainer v-drop></MyContainer>

新たな問題が発生します。データを転送するためにドラッグ操作を実行します。ただし、データ転送の初期段階はカスタム命令ドラッグのバインド フックで実行され、データ転送の受信段階はドロップのバインド フックで実行されます。では、データはどこから来るのでしょうか。どこに行くの?当然、データはコンポーネントから取得され、別のコンポーネントにも渡される必要があります。そうしないと、vue コンポーネントにディレクティブを記述する意味がありません。

幸いなことに、カスタム命令のフック関数は、コンポーネントにアクセスするための最も簡単で効果的な方法を提供します。それは、フック関数の 3 番目のパラメーター vnode です。vnode には、componentInstance と呼ばれる属性があります。この componentInstance は、カスタム命令のホスト、つまり vue コンポーネント インスタンスです。

次のステップは簡単です。v-drag が追加されたコンポーネントのドラッグ データを取得するためのインターフェイスと、v-drop が追加されたコンポーネントのドラッグ データを受信するためのインターフェイスを定義するだけです。 Vue コンポーネントはインターフェースの定義をサポートしていませんが、2 つのメソッド名に同意して、コンポーネントのメソッドに実装することができます。

//カスタム コンポーネントの内部メソッド:{
  getDragData(){ //getDragData は、コンポーネントのドラッグ データを取得するためのインターフェイス メソッドであることに同意します。 return this.id; //このコンポーネントがドラッグされたときに、ID を渡す必要があると想定します。}
  setDragData(data){ //setDragData は、コンポーネントがドラッグ データを受け取るためのインターフェイス メソッドとして承認されています。this.appendNewChildById(data); //このコンポーネントは、新しい要素を生成するために ID を受け取ると想定します}
}

次に、ドラッグ データ コードを設定して渡すようにカスタム命令を書き直します。

dragValue を "" にします。
if(vnode.componentInstance.getDragData != 未定義){
  ドラッグ値 = vnode.componentInstance.getDragData();
}
event.dataTransfer.setData("テキスト", dragValue);

v-drop ディレクティブの ondrop イベント

dragValue を event.dataTransfer.getData('Text') にします。
if(vnode.componentInstance.setDragData != 未定義){
  vnode.componentInstance.setDragData(ドラッグ値);
}

インターフェース制約がないとコンポーネントがこれらのメソッドを実装しない可能性があるため、コンポーネントのインターフェース メソッドにアクセスするときに if チェックを追加しました。

さて、ここでは、コンポーネントをドラッグ アンド ドロップするためのカスタム命令を完全に実装しました。シンプルですが、非常に実用的で柔軟性があり、基本的に日常のドラッグ アンド ドロップのニーズを満たすことができます。プロセス全体をまとめてみましょう。

  • グローバルディレクティブv-dragとv-dropをカスタマイズする
  • ドラッグされたコンポーネントは、データを取得するためのインターフェースメソッドを実装する必要がある
  • 配置する必要があるコンポーネントは、データを受信するためのインターフェースメソッドを実装します
  • ドラッグコマンドはコンポーネントのインターフェースメソッドにアクセスしてデータを取得します。
  • ドロップ命令はコンポーネントのインターフェースメソッドにアクセスしてデータを渡す

グローバル カスタム ディレクティブの関連コードを es6 クラスにカプセル化し、別の js ファイルとしてプロジェクトに配置するか、npm に公開してから、このクラスを main.js にインポートし、静的初期化メソッドを呼び出して、グローバル ディレクティブの登録を完了します。この方法では、プロジェクト内のどのコンポーネントでも v-drag と v-drop を使用できます。上記でまとめた 5 つの手順のうち、実装する必要があるのは 2 番目と 3 番目の手順だけです。

上記は、vue カスタム命令を使用してドラッグ アンド ドロップ プラグインを構築する方法の詳細です。ドラッグ アンド ドロップ プラグインを構築するための vue カスタム命令の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Moment プラグインを使用して時間をフォーマットする vue のサンプルコード
  • vue+element を使用した Google プラグインの開発プロセス全体
  • スワイパープラグインを使用して Vue でカルーセルを実装する例
  • VueにExcelテーブルプラグインを導入する方法
  • Vue コード強調プラグインの総合的な比較と評価
  • vue-simple-uploader をベースに、ファイルセグメントアップロード、インスタントアップロード、ブレークポイント再開のグローバルアップロードプラグイン機能をカプセル化します。
  • vue-cli 3 で vue-bootstrap-datetimepicker 日付プラグインを使用する方法
  • Vue プラグイン エラー: このページで Vue.js が検出されました。問題は解決しました

<<:  MySQLは、where in()順序ソートを実装するためにfind_in_set()関数を使用します。

>>:  Docker を使用して Spring Boot をデプロイする方法の例

推薦する

MySQLにおける区切り文字の定義と機能の詳細な説明

MySQL を初めて学ぶときは、区切り文字の本当の目的を理解していないかもしれません。区切り文字は、...

MySQLデータベースに中国語の文字を保存するときに発生するエラーを解決する方法を教えます

目次1. 遭遇した問題2. 問題を分析する3. 本当の問題4. 解決策5. ソリューション効果1. ...

Excelアップロード機能を実現するVue + iViewの完全コード

1. HTML部分 <Col span="2">ファイルをアップロー...

JS+Canvas でダイナミックな時計効果を実現

参考までに、Canvas をベースにしたダイナミッククロックのデモを用意しました。具体的な内容は次の...

jsネイティブ構文プロトタイプ、__proto__、コンストラクタの徹底的な理解

目次1 はじめに2 前提条件2.1 データ型2.2 それが自身のプロパティであるかどうかを判断する ...

MySQL マスタースレーブレプリケーションの実践の詳細説明 - ログポイントに基づくレプリケーション

ログポイントベースのレプリケーション1. マスターデータベースとスレーブデータベースに専用のレプリケ...

DockerはRedisを起動し、パスワードを設定します

RedisはRedisバージョン5のapline(Alps)イメージを使用します。これは小さくて高速...

Django が uwsgi+nginx プロキシで静的リソースにアクセスできない問題の解決方法

uwsgi+nginx プロキシ Django をデプロイする場合、uwsgi を使用したアクセスは...

Linux でファイルプレフィックスを一括で追加する方法

フォルダー内のすべての txt ファイルのファイル名の前に「gt_」を追加する必要があります。つまり...

Ubuntu環境でのPHP関連のパスと変更方法

Ubuntu環境におけるPHP関連パスPHP パス /usr/bin/php phpize5 /us...

docker を使用して minio と java sdk を構築するプロセスの詳細な説明

目次1minioはシンプル2 Dockerビルド minio 2.1 単一ノード2.2 マルチノード...

Centos7 での MySQL のインストールに関するチュートリアル

最近、自宅サーバーにクラウドディスクを導入する予定なので、一連の環境構築作業を始めました。MySQL...

dockerでlnmp環境を構築する方法

プロジェクトディレクトリを作成する php ディレクトリをコピーする次のプロジェクト構造を作成します...