ドラッグ アンド ドロップ API は、ドラッグ可能な要素を HTML に追加し、ドラッグ可能な豊富な UI 要素を備えた Web アプリケーションを構築できるようにします。 この記事では、Vue.js を使用してシンプルなカンバン アプリケーションを構築します。 Kanban は、ユーザーがプロジェクトを最初から最後まで視覚的に管理できるプロジェクト管理ツールです。 Trello、Pivotal Tracker、Jira などのツールは、カンバン アプリの例です。 ボードのセットアップ次のコマンドを実行して、カンバン プロジェクトを作成します。 vue カンバンボードを作成する プロジェクトを作成するときに選択する項目には、Babel と ESlint のデフォルトのプリセットのみが含まれます。 完了したら、デフォルトのコンポーネント HelloWorld を削除し、App コンポーネントを空にして、ベア コンポーネント テンプレートのみを含むように変更します。 <テンプレート> <div></div> </テンプレート> <スクリプト> エクスポートデフォルト{ 名前: 'アプリ'、 コンポーネント: {}, }; </スクリプト> <スタイル></スタイル> 次に、スタイリングに Bootstrap を使用します。必要なのは Bootstrap CSS CDN だけです。これをpublic/index.htmlの先頭に追加します。 <ヘッド> <メタ文字セット="utf-8"> <meta http-equiv="X-UA-compatible" content="IE=edge"> <meta name="viewport" content="width=デバイス幅,初期スケール=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico" rel="外部 nofollow" > <link rel="スタイルシート" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="外部 nofollow" 整合性="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" クロスオリジン="匿名"> <title><%= htmlWebpackPlugin.options.title %></title> </head> カンバンでUIコンポーネントを構築するボードは次のようになります。 通常、ボードには列とカードがあります。カードは実行される個々の項目またはタスクであり、列は特定のカードの状態を表示するために使用されます。 したがって、列用、カード用、新しいカードを作成するための 3 つの Vue コンポーネントを作成する必要があります。 カードコンポーネントの作成まずカードコンポーネントを作成しましょう。 /component ディレクトリに新しいファイル Card.vue を作成します。 コンポーネントに次のコードを追加します。 <テンプレート> <div class="カード"> <div class="card-body">サンプルカード</div> </div> </テンプレート> <スクリプト> デフォルトをエクスポートします {}; </スクリプト> <スタイルスコープ> div.カード{ 下部マージン: 15px; ボックスシャドウ: 0 0 5px #cccccc; 遷移: すべての緩和 300 ミリ秒; 背景: #fdfdfd; } div.card:hover { ボックスシャドウ: 0 0 10px #aaaaaa; 背景: #ffffff; } </スタイル> これにより、カード コンポーネントが作成され、スタイル設定されます。ただし、これはコンポーネントの骨組みに過ぎないため、コンポーネントにドラッグ可能な機能はまだ追加されていません。 AddCardコンポーネントの作成名前が示すように、このコンポーネントは新しいカードを作成し、それを列に追加する役割を担います。 /components ディレクトリに AddCard.vue ファイルを作成し、次のコードを追加します。 <テンプレート> <divクラス=""> <ボタン クラス="btn btn-sm btn-info w-100" v-if="!inAddMode" @click="inAddMode = true" > カードを追加 </ボタン> <form action="#" class="card p-3" ref="form" v-else> <div class="フォームグループ"> <入力 タイプ="テキスト" 名前="タイトル" id="タイトル" クラス="フォームコントロール" placeholder="何か興味深いもの..." v-model="カードデータ" /> </div> <div class="d-flex justify-content-center"> <button type="submit" class="btn w-50 btn-primary mr-3">保存</button> <button type="reset" class="btn w-50 btn-danger"> キャンセル </ボタン> </div> </フォーム> </div> </テンプレート> <スクリプト> エクスポートデフォルト{ データ() { 戻る { inAddMode: false、 カードデータ: ''、 }; }, メソッド: {}, }; </スクリプト> <スタイル></スタイル> 具体的な機能は後ほど構築します。 列コンポーネントの作成この最後のコンポーネントはカードのリストを表示するために使用され、列に直接新しいカードを作成できるように AddCard コンポーネントも含まれています。 コンポーネント ディレクトリに Column.vue ファイルを作成し、次のコードを追加します。 <テンプレート> <div class="col-md-3 カード列" ref="列"> <ヘッダークラス="カードヘッダー"> <h3 class="col">列名</h3> </ヘッダー> <div class="カードリスト"></div> </div> </テンプレート> <スクリプト> デフォルトをエクスポートします {}; </スクリプト> <スタイルスコープ> div.列{ パディング: 0; パディング下部: 15px; マージン: 0 15px; ボックスシャドウ: 0 0 10px #cccccc; } div.カードリスト{ パディング: 0 15px; } ヘッダー { 下マージン: 10px; } ヘッダー h3 { テキスト配置: 中央; } </スタイル> プロジェクトのフレームワークが設定されたので、ブラウザでドラッグ アンド ドロップがどのように機能するかの概要を見てみましょう。 HTML5 ドラッグ アンド ドロップ API とは何ですか?ドラッグ操作は、ユーザーがマウスをドラッグ可能な要素の上に移動し、次にその要素をドラッグ アンド ドロップ対応の要素の上に移動したときに開始されます。 デフォルトでは、ドラッグ可能な HTML 要素は画像とリンクのみです。他の要素をドラッグ可能にするには、要素に draggable 属性を追加する必要があります。また、要素を選択して draggable 属性を true に設定することで、JavaScript で明示的に機能を作成することもできます。 要素の draggable 属性を true に設定すると、要素に draggable 属性が追加されていることがわかります。 <!-- HTML で要素をドラッグ可能にする --> <div draggable="true">これは HTML 内のドラッグ可能な div です</div> <スクリプト> // JavaScript で要素をドラッグ可能にする div は document.querySelector('div') に格納されます。 div.draggable = true; </スクリプト> ドラッグ要素の目的は、ページのある部分から別の部分にデータを転送することです。 画像の場合、転送されるデータは画像の URL またはその Base 64 表現です。リンクの場合、転送されるデータは URL です。リンクをブラウザの URL バーに移動すると、ブラウザがその URL にジャンプします。 したがって、データを転送する機能がなければ、要素をドラッグしても意味がありません。ドラッグ操作によって転送されたデータは、ドラッグ アンド ドロップ操作中にデータを保存およびアクセスする方法を提供する DataTransfer API を介してドラッグ データ ストアに保存できます。 DataTransfer は、ドラッグ アンド ドロップで転送するアイテムを追加する場所を提供します。ドラッグ操作が開始されたとき (dragstart イベントが呼び出されたとき) にデータをドラッグ データ ストアに追加することができ、ドラッグ アンド ドロップ操作が完了した後 (drop イベントが呼び出されたとき) にのみデータを受信できます。 要素をドラッグしてから解放するまでの期間中、要素がドラッグ アンド ドロップされた後、ドラッグされた要素に対して dragstart と dragend の 2 つのイベントがトリガーされます。 ドラッグ可能な要素をどこにでもドラッグ アンド ドロップすることはまだできません。要素を明示的にドラッグ可能にする必要があるだけでなく、ドロップも有効にする必要があります。 要素のドラッグ アンド ドロップを有効にするには、dragover イベントをリッスンし、デフォルトのブラウザ アクションを防止する必要があります。 <!-- セクションをドロップ可能にする --> <セクションクラス="セクション"></セクション> <スクリプト> セクション = document.querySelector('.section'); section.addEventListener('dragover', (e) => { e.preventDefault(); }); </スクリプト> 要素がドラッグ アンド ドロップ対応の要素にドラッグされると、ドラッグ アンド ドロップ対応の要素で次のイベントが発生します。 Dragenter: ドラッグアンドドロップが可能な要素の上に要素がドラッグされたときに1回発生します。 DataTransfer オブジェクトに保存されたデータは、dragenter や dragover ではなく、ドロップ イベントがトリガーされたときにのみアクセスできることに注意することが重要です。 すべてのコンポーネントを組み立てるコンポーネントにドラッグ アンド ドロップ機能を追加する前に、アプリの状態について説明しましょう。 ここで、アプリの状態は App コンポーネントに保存され、その後、Column コンポーネントにプロパティとして渡すことができます。一方、列コンポーネントはレンダリング時に必要なプロパティをカードコンポーネントに渡します。 状態とコンポーネントの構成を反映するように App.vue を変更します。 // アプリ.vue <テンプレート> <div class="コンテナ流体"> <h2 class="m-5"> Vue カンバンボード </h2> <div class="行の中央揃え"> <コラム v-for="(列、インデックス) 列内" :column="列" :key="インデックス" /> </div> </div> </テンプレート> <スクリプト> './components/Column' から列をインポートします。 エクスポートデフォルト{ 名前: 'アプリ'、 コンポーネント: カラム、 }, データ() { 戻る { 列: [ { 名前: 'TO-DO'、 カード: { 値: '朝食を準備する'、 }, { 価値: '市場に行く'、 }, { 値: '洗濯をする'、 }, ]、 }, { 名前: '進行中'、 カード: [], }, { 名前: '完了'、 カード: [], }, ]、 }; }, }; </スクリプト> <スタイル> h2 { テキスト配置: 中央; } </スタイル> ここでは、列コンポーネントをインポートし、列状態のデータをループしながら各列のデータを列コンポーネントに渡しました。この場合、「To-Do」、「進行中」、「完了」の 3 つの列のみがあり、各列にはカードの配列があります。 次に、Column コンポーネントを更新して、props を受け取って表示します。 // 列.vue <テンプレート> <div class="col-md-3 カード列" ref="列"> <header class="カードヘッダー"> <h3 class="col">{{ 列名 }}</h3> <カードを追加 /> </ヘッダー> <div class="カードリスト"> <Card v-for="(card, index) in column.cards" :key="index" :card="card" /> </div> </div> </テンプレート> <スクリプト> './Card' から Card をインポートします。 './AddCard' から AddCard をインポートします。 エクスポートデフォルト{ 名前: '列', コンポーネント: カード、 カードを追加、 }, 小道具: { カラム: { タイプ: オブジェクト、 必須: true、 }, }, }; </スクリプト> ... Column コンポーネントは App コンポーネントから props を受け取り、その props を使用して Card コンポーネント リストをレンダリングします。新しいカードを列に直接追加できるようにする必要があるため、ここでは AddCard コンポーネントも使用されます。 最後に、カード コンポーネントが更新され、列から受信したデータが表示されます。 // カード.vue <テンプレート> <div class="カード" ref="カード"> <div class="card-body">{{ card.value }}</div> </div> </テンプレート> <スクリプト> エクスポートデフォルト{ 名前: 'カード', 小道具: { カード: { タイプ: オブジェクト、 必須: true、 }, }, }; </スクリプト> カード コンポーネントは、必要なすべてのデータを列から受け取って表示するだけです。ここでは、カード要素への参照も追加します。これは、JavaScript を使用してカード要素にアクセスするときに便利です。 上記の手順を完了すると、アプリケーションは次のようになります。 ドラッグアンドドロップ機能の追加ドラッグ アンド ドロップ機能を追加する最初のステップは、ドラッグ可能なコンポーネントとドロップ ターゲットを識別することです。 ユーザーは、カード内のアクティビティの進行に合わせて、カードをある列から別の列にドラッグできる必要があります。したがって、ドラッグ可能なコンポーネントはカード コンポーネントであり、ドロップ ターゲットは列コンポーネントである必要があります。 カードをドラッグ可能にするカード コンポーネントをドラッグ可能にするには、次の手順を実行する必要があります。
まず draggable を true に設定する必要があります。Vue ライフサイクル フックによると、安全な場所はインストールされたフックである必要があります。 Card コンポーネントのマウントされたフックに以下を追加します。 // カード.vue <スクリプト> エクスポートデフォルト{ 名前: 'カード', プロパティ: {...}, マウント() { this.setDraggable(); }, メソッド: { ドラッグ可能な設定() { // カード要素を取得します。 const カード = this.$refs.card; カードのドラッグ可能 = true; // イベント リスナーを設定します。 card.addEventListener('dragstart', this.handleDragStart); card.addEventListener('dragend', this.handleDragEnd); }, }, </スクリプト> 上記では、カード コンポーネントをドラッグ可能にする setDraggable メソッドを作成しました。 setDraggable では、前のセクションで追加した参照からカードを取得し、draggable プロパティを true に設定します。 イベント リスナーも設定する必要があります。 // カード.vue <スクリプト> エクスポート const CardDataType = 'text/x-kanban-card'; エクスポートデフォルト{ ... メソッド: { setDraggable() {...}, handleDragStart(イベント) { イベントの dataTransfer を定数に設定します。 // プロパティから取得したカードの値をデータとして設定します。 dataTransfer.setData(CardDataType、this.card.value); dataTransfer.effectAllowed = '移動'; // カードが所定の位置にないことを示す視覚的な合図を追加します。 イベントターゲットスタイルの不透明度 = 0.2; }, handleDragEnd(イベント) { // カードをドロップしたときに不透明度を通常に戻します。 イベントターゲットスタイルの不透明度 = 1; } } } </スクリプト> 前述したように、ドラッグ データ ストアにデータを追加できるのは、dragstart イベントが呼び出されたときのみです。したがって、handleDragStart メソッドにデータを追加する必要があります。 データを設定するときに使用する重要な情報は、文字列にすることができる形式です。私たちの場合、text/x-kanban-card に設定されています。カードを削除した後にデータを取得するときに列コンポーネントがこのデータ形式を使用するため、このデータ形式を保存してエクスポートします。 最後に、カードの透明度を 0.2 に下げて、カードが実際に元の位置から引き出されたことをユーザーにフィードバックします。ドラッグが完了したら、透明度を 1 に戻します。 カードをドラッグできるようになりました。次に、ドロップターゲットを追加します。 ドラッグオーバーをドロップ有効に設定するカードを列コンポーネントにドラッグすると、dragover イベントがすぐに発生し、カードが列にドロップされると drop イベントが発生します。 カードを列にドロップするには、これらのイベントをリッスンする必要があります。 // 列.vue <テンプレート>...</テンプレート> <スクリプト> './Card' から Card { CardDataType } をインポートします。 './AddCard' から AddCard をインポートします。 エクスポートデフォルト{ 名前: '列', コンポーネント: {...}, プロパティ: {...}, マウント() { これをenableDrop(); }, メソッド: { ドロップを有効にする() { 定数列 = this.$refs.column; column.addEventListener('dragenter', this.handleDragEnter); column.addEventListener('dragover', this.handleDragOver); column.addEventListener('drop', this.handleDrop); }, /** * @param {DragEvent} イベント */ handleDragEnter(イベント) { イベントデータ転送タイプに[CardDataType]が含まれる場合 // カードのみを処理します。 イベントをデフォルトにしない(); } }, handleDragOver(イベント) { // 移動効果を作成します。 event.dataTransfer.dropEffect = '移動'; イベントをデフォルトにしない(); }, /** * @param {DragEvent} イベント */ ハンドルドロップ(イベント) { const データ = event.dataTransfer.getData(CardDataType); // カード移動イベントを発行します。 this.$emit('cardMoved', データ); }, }, }; </スクリプト> ここで、列コンポーネントがマウントされた後にドロップを有効にするために必要なイベント リスナーを設定します。 3 つのイベントのうち、最初にトリガーされるのは dragenter です。これは、ドラッグ可能な要素が列にドラッグされるとすぐにトリガーされます。私たちのプログラムでは、カードを列に配置するだけなので、dragenter イベントでは、カード コンポーネントで定義されたカード データ型を含むデータ型のデフォルト値のみを防止します。 dragover イベントで、ドロップ効果を移動するように設定します。 ドロップ イベントで dataTransfer オブジェクトから転送されたデータを取得します。 次に、状態を更新し、カードを現在の列に移動する必要があります。プログラムの状態は App コンポーネント内にあるため、ドロップ リスナーで cardMoved イベントを発行し、転送されたデータを渡し、App コンポーネントで cardMoved イベントをリッスンします。 CardMoved イベントをリッスンするように App.vue を更新します。 // アプリ.vue <テンプレート> <div class="コンテナ流体"> ... <div class="行の中央揃え"> <コラム v-for="(列、インデックス) 列内" :column="列" :key="インデックス" @cardMoved="カードを列に移動($event、列)" /> </div> </div> </テンプレート> <スクリプト> './components/Column' から列をインポートします。 エクスポートデフォルト{ 名前: 'アプリ'、 コンポーネント: {...}, データ() { 戻る {...} }, メソッド: { カードを列に移動(データ、新しい列) { const 以前の列 = this.columns.find(列 => { // 列内のすべてのカードの値を取得します。 const cardValues = column.cards.map((card) => card.value); cardValues.includes(データ) を返します。 }) // 前の列からカードを削除します。 以前の列.カード = 以前の列.カード.フィルター( (カード) => カード.値 !== データ ); // 新しい列にカードを追加します。 newColumn.cards.push({ 値: データ }); }, }, } </スクリプト> ここでは、@cardMoved を通じて cardMoved イベントがリッスンされ、moveCardToColumn メソッドが呼び出されます。 cardMoved イベントは、$event を介してアクセスできる値 (カード データ) を発行し、カードがドロップされた現在の列 (イベントがディスパッチされた場所) も渡されます。 moveCardToColumn 関数は、カードが以前配置されていた列を見つけ、その列からカードを削除し、最後にカードを新しい列に追加するという 3 つの処理を実行します。 ボードを完成させるドラッグ アンド ドロップ機能が実装されたので、残っているのはカードを追加する機能だけです。 AddCard.vue に次のコードを追加します。 <テンプレート> <divクラス=""> <ボタン クラス="btn btn-sm btn-info w-100" v-if="!inAddMode" @click="inAddMode = true" > カードを追加 </ボタン> <フォーム アクション="#" クラス="カード p-3" @submit.prevent="送信処理" @reset="ハンドルリセット" ref="フォーム" v-else > ... </フォーム> </div> </テンプレート> <スクリプト> エクスポートデフォルト{ データ() { 戻る {...}; }, メソッド: { ハンドル送信() { if (this.cardData.trim()) { this.cardData = ''; this.inAddMode は false です。 this.$emit('newcard', this.cardData.trim()); } }, ハンドルリセット() { this.cardData = ''; this.inAddMode は false です。 }, }, }; </スクリプト> 上記のコードは、「カード追加」フォームが送信またはリセットされたときに実行される関数です。 リセット後に cardData をクリアし、inAddMode を false に設定します。 また、フォームを送信した後、cardData をクリアして、新しい項目を追加するときに以前のデータが表示されないようにし、inAddMode を false に設定して newcard イベントを発行します。 AddCard コンポーネントは Column コンポーネントで使用されるため、Column コンポーネントで newcard イベントをリッスンする必要があります。 Column コンポーネントで newcard イベントをリッスンするコードを追加します。 <テンプレート> <div class="col-md-3 カード列" ref="列"> <header class="カードヘッダー"> <h3 class="col">{{ 列名 }}</h3> <AddCard @newcard="$emit('newcard', $event)"></AddCard> </ヘッダー> ... </テンプレート> ... ここで newcard イベントを再発行すると、実際のアクションが実行される App コンポーネントに到達できるようになります。 カスタム Vue イベントはバブルしないため、App コンポーネントは直接の子コンポーネントではないため、AddCard コンポーネントから発行された newcard イベントをリッスンできません。 // アプリ.vue <テンプレート> <div class="コンテナ流体"> ... <div class="行の中央揃え"> <コラム v-for="(列、インデックス) 列内" :column="列" :key="インデックス" @cardMoved="カードを列に移動($event、列)" @newcard="handleNewCard($event, 列)" /> </div> </div> </テンプレート> <スクリプト> './components/Column' から列をインポートします。 エクスポートデフォルト{ 名前: 'アプリ'、 コンポーネント: {...}, データ() { 戻る {...} }, メソッド: { カードを列に移動(データ、新しい列) {...}, handleNewCard(データ、列) { // 列に新しいカードを追加します。 column.cards.unshift({ 値: データ }); }, }, }; </スクリプト> ここでは、Column コンポーネントから呼び出される newcard イベントをリッスンし、データを取得した後、新しいカードを作成し、作成した列に追加します。 要約するこの記事では、HTML 5 ドラッグ アンド ドロップ API とは何か、どのように使用するのか、そして Vue.js でどのように実装するのかを紹介しました。 ドラッグ アンド ドロップ機能は、他のフロントエンド フレームワークやネイティブ JavaScript でも使用できます。 上記は、Vue で HTML 5 ドラッグ アンド ドロップ API を使用する方法の詳細です。Vue のドラッグ アンド ドロップ API の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: Vue で SVG アイコンを導入する 2 つの方法
目次概要コードの実装シングルトンパターンの簡易版改良版プロキシバージョンシングルトンモード遅延シング...
序文以前、defineProperty を紹介したとき、オブジェクトの変更のみを監視でき、配列の変更...
序文最近、MySQL に関するメモをいくつか尋ねる人がいたので、ブログ記事を書かなければなりません。...
1. CSS3の三角形は特殊効果でズームし続けます11.1 画像プレビュー 11.2 index.h...
1. ホットリンクの原則1.1 Webページの準備Web ソース ホスト (192.168.153...
エラーは次のとおりです:キャッチされない TypeError: 未定義のプロパティ 'mod...
Windowsユーザー向けDocker で openGauss を使用するopenGaussイメージ...
スタンドアロンの hbase について、まずは説明しましょう。 Dockerをインストールするまず ...
感想:私はバックエンド開発者です。静的 (HTML) ページを取得すると、ページ構造と命名規則が極端...
私は通常、大手ウェブサイトの特別ページや製品リリースページを訪問するのが好きです。なぜなら、たくさん...
html ¶ <html></html> html:xml ¶ <ht...
1. MySQLデータベースをダウンロードし、インストールして設定するダウンロードアドレス: htt...
以下のコンテンツのオペレーティング システムは次のとおりです: Centos 6.7 yum で M...
目次1. 異なるビューポートを取得する方法2. 水平画面と垂直画面のJavaScript検出3. 水...
目次1. UDPとLinuxの基礎の紹介2. 各機能の使い方1. ソケット機能の使用2. バインド機...