Vueのドラッグ可能なコンポーネントであるVue Smooth DnDの使用方法の詳細な説明

Vueのドラッグ可能なコンポーネントであるVue Smooth DnDの使用方法の詳細な説明

紹介とデモ

最近、ドラッグアンドドロップリストが必要になり、シンプルで使いやすい Vue ドラッグ可能コンポーネントを見つけました。アムウェイ

Vue Smooth DnD は、smooth-dnd ライブラリをラップする、高速で軽量なドラッグ アンド ドロップ、ソート可能な Vue.js ライブラリです。

Vue Smooth DnD は主にContainerDraggable 2 つのコンポーネントで構成されています。 Containerにはドラッグ可能な要素またはコンポーネントが含まれており、その子要素はすべてDraggableでラップされる必要があります。ドラッグ可能にするすべての要素は、 Draggableでラップする必要があります。

インストール: npm i vue-smooth-dnd

コンポーネントの基本的な使用方法を示し、ドラッグ可能なリストを実装する簡単なデモです。

<テンプレート>
    <div>
        <div class="シンプルページ">
            <コンテナ @drop="onDrop">
                <ドラッグ可能な v-for="item in items" :key="item.id">
                    <div class="ドラッグ可能なアイテム">
                        {{item.data}}
                    </div>
                </ドラッグ可能>
            </コンテナ>
        </div>
    </div>
</テンプレート>

<スクリプト>
    「vue-smooth-dnd」から Container、Draggable をインポートします。

    const applyDrag = (arr, dragResult) => {
        const { removedIndex, addedIndex, payload } = dragResult
        console.log(削除されたインデックス、追加されたインデックス、ペイロード)
        if (removedIndex === null && addedIndex === null) は arr を返します。

        const 結果 = [...arr]
        itemToAdd = ペイロード

        if (削除されたインデックス !== null) {
            追加する項目 = result.splice(削除されたインデックス、1)[0]
        }

        追加されたインデックスが null の場合
            結果.splice(追加されたインデックス、0、追加する項目)
        }

        結果を返す
    }

    const generateItems = (count, 作成者) => {
        定数結果 = []
        (i = 0 とします; i < count; i++) {
            結果.push(作成者(i))
        }
        結果を返す
    }

    エクスポートデフォルト{
        名前:「シンプル」
        コンポーネント: { コンテナ、ドラッグ可能 },
        データ() {
            戻る {
                アイテム: generateItems(50, i => ({ id: i, data: "Draggable " + i }))
            };
        },
        メソッド: {
            onDrop(ドロップ結果) {
                this.items = applyDrag(this.items、dropResult);
            }
        }
    };

</スクリプト>

<スタイル>
    .ドラッグ可能なアイテム{
        高さ: 50px;
        行の高さ: 50px;
        テキスト配置: 中央;
        表示: ブロック;
        背景色: #fff;
        アウトライン: 0;
        境界線: 1px実線 rgba(0, 0, 0, .125);
        下マージン: 2px;
        上マージン: 2px;
        カーソル: デフォルト;
        ユーザー選択: なし;
    }
</スタイル>

効果

API: コンテナ

財産

財産タイプデフォルト値説明する
:方向垂直コンテナの向き(水平または垂直)
:行動動く説明 ドラッグされた要素は、ターゲット コンテナーに移動またはコピーされます。 移動、コピー、ドロップゾーン、または包含が可能です。 move はコンテナー間で要素を移動できます。copy は要素を他のコンテナーにコピーできますが、コンテナー内の要素は不変です。drop-zone はコンテナー間で要素を移動できますが、コンテナー内の要素の順序は固定です。 contain はコンテナ内でのみ移動できます。
:タグ文字列、ノードの説明分割コンテナの要素タグ。デフォルトは div で、tag="table" などの文字列、または value 属性と props 属性を含むオブジェクトになります: tag="{value: 'table', props: {class: 'my-table'}}"
:グループ名未定義ドラッグ可能な要素は、同じグループ名を持つコンテナー間で移動できます。グループ名が設定されていない場合、コンテナーは外部からの要素を受け入れません。 この動作は、shouldAcceptDrop 関数によって上書きできます。 以下を参照してください。
:ロック軸未定義ドラッグしている移動軸をロックします。可能な値は x、y、または undefined です。
:ドラッグハンドルセレクター未定義ドラッグを可能にする CSS セレクターを指定するために使用されます。指定しない場合は、要素内の任意の位置をつかむことができます。
:非ドラッグ領域セレクター未定義ドラッグを無効にする CSS セレクターは、dragHandleSelector よりも優先されます。
:ドラッグ開始遅延番号0 (タッチデバイスの場合は200)単位はミリ秒です。要素をクリックしてからドラッグを開始するまでにかかる時間を示します。これより前にカーソルを 5 ピクセル以上移動すると、ドラッグはキャンセルされます。
:アニメーション期間番号250単位はミリ秒です。要素を配置および並べ替えるためのアニメーションの継続時間を示します。
:自動スクロールが有効ブール値真実ドラッグされた項目が境界線に近づくと、最初のスクロール可能な親が自動的にスクロールします。 (この属性は分かりません==)
:ドラッグクラス未定義要素がドラッグされている間に追加されたクラス (ドラッグ終了後の要素の表示には影響しません)。
:ドロップクラス未定義ドラッグされた要素がドロップされてからページに追加されるまでに追加されるクラス。
:ドロップアウト時に削除ブール値未定義trueに設定すると、ドラッグされた要素が関連するコンテナにドロップされない場合、要素インデックスをremovedIndexとしてonDrop()が呼び出されます。
:ドロッププレースホルダーブール値、オブジェクト未定義プレースホルダー オプション。 className、animationDuration、showOnTop が含まれます

drag-classdrop-classdrop-placeholder.classNameの効果のデモンストレーション

<コンテナ #他のプロパティを省略...
        :animation-duration="1000" # 要素を配置した後のアニメーション遅延 drag-class="card-ghost"         
        ドロップクラス="カードゴーストドロップ"
        :ドロッププレースホルダー="{
            className: 'drop-preview'、# プレースホルダー スタイル animationDuration: '1000'、# プレースホルダー アニメーション遅延 showOnTop: true # 他の要素の上に表示するかどうか。false に設定すると、他のドラッグ要素によって覆われます。}"
>
    <!-- ドラッグ可能な要素 -->
    <ドラッグ可能>....</ドラッグ可能>
</コンテナ>

クラス対応スタイル

.カードゴースト{
    遷移: 変換 0.18 秒のイーズ;
    変換: rotateZ(35deg);
    背景: 赤 !重要;
}
.カードゴーストドロップ{
    遷移: transform 1s cubic-bezier(0,1.43,.62,1.56);
    変換: rotateZ(0deg);
    背景: 緑 !重要;
}
.drop-preview {
    境界線: 1px 破線 #abc;
    マージン: 5px;
    背景: 黄色 !重要;
}

実際の効果(私の優れたカラーマッチング)

ライフサイクル

ドラッグのライフサイクルは、一連のコールバックとイベントによって記述および制御されます。次の例には、説明のために 3 つのコンテナーが含まれています (ドキュメントは翻訳されずに直接コピーされます。API の詳細な説明は後で確認できます)。

マウスコールコールバック/イベントパラメータ注記

下 o 最初のクリック

移動 o 初期ドラッグ
       |
       | get-child-payload() インデックス関数はペイロードを返す必要があります
       |
       | 3 x should-accept-drop() srcOptions、payload すべてのコンテナに対して実行されます
       |
       | 3 x ドラッグ開始ドラッグ結果がすべてのコンテナに対して発動される
       |
       | ドラッグして入力
       ヴ

コンテナ上をドラッグして移動
       |
       | nx drag-leave ドラッグ可能なコンテナが離れると起動されます
       | nx drag-enter ドラッグ可能なものがコンテナに入ると発火します
       ヴ

上へドラッグ終了

                 should-animate-drop() srcOptions、payload ドロップされたコンテナに対して1回実行されます

           3 x ドラッグ終了ドラッグ結果がすべてのコンテナに対して発火しました

           nx drop dropResult ドロップ可能なコンテナに対してのみ実行されます

should-accept-dropは、すべてのdrag-start前とすべてのdrag-endの前にトリガーされる必要がありますが、わかりやすくするためにここでは省略されていることに注意してください。

dragResultパラメータの形式は次のとおりです。

ドラッグ結果: {
    payload, # ペイロードはドラッグされているオブジェクトとして理解できます isSource, # ドラッグされているのはコンテナー自体ですか willAcceptDrop, # ドロップできますか? }

dropResultパラメータの形式は次のとおりです。

ドロップ結果: {
    addedIndex、# 配置する新しく追加された要素のインデックス、または要素がない場合は null
    removedIndex、# 削除する要素のインデックス、または要素がない場合は null
    payload, # ドラッグされた要素オブジェクト。getChildPayload で指定できます。droppedElement, # 配置された DOM 要素}

コールバック

コールバックは、ユーザーとの対話の前と最中に追加のロジックとチェックを提供します。

  • get-child-payload(index) onDrop()に渡されるpayloadオブジェクトをカスタマイズします。
  • should-accept-drop(sourceContainerOptions, payload)は、コンテナをドロップできるかどうかを決定するために使用され、 group-name属性をオーバーライドします。
  • should-animate-drop(sourceContainerOptions, payload)ドロップアニメーションを防ぐためにfalse返します。
  • get-ghost-parent()ゴースト要素 (ドラッグ時に表示される要素) を追加する要素を返します。デフォルトは親要素です。場合によっては、配置によって問題が発生することがあります。document.body document.body返すなど、カスタマイズすることもできます。

イベント

  • @drag-startドラッグが開始されたときにすべてのコンテナーによって発行されるイベント。パラメータdragResult
  • @drag-endドラッグが終了したときにすべてのコンテナーによって呼び出される関数。 @dropイベントの前に呼び出されます。パラメータdragResult
  • @drag-enterドラッグされた項目がドラッグ中にその境界内に入るたびに、関連付けられたコンテナーによって発行されるイベント。
  • @drag-leaveドラッグされた項目がドラッグ中に境界を離れるたびに、関連付けられたコンテナーによって発行されるイベント。
  • @drop-readyコンテナー内のドロップ可能な位置のインデックスが変更されたときに、ドラッグされたコンテナーが呼び出す関数。基本的に、コンテナー内のドラッグ可能な項目がスライドして、ドラッグされた項目のためのスペースが空くたびに呼び出されます。パラメータdropResult
  • 配置が完了したとき (配置アニメーションが完了した後) に、関連するすべてのコンテナーによって発行される@dropイベント。ソース コンテナーと、ドロップを受け入れることができるすべてのコンテナーは関連していると見なされます。パラメータdropResult

API: ドラッグ可能

tag

コンテナと同じtag 、ドラッグ可能な要素の DOM 要素タグを指定します。

実際の戦闘

シンプルなチームコラボレーションタスクマネージャーを実装します。

<テンプレート>
    <div class="カードシーン">
        <コンテナ
                方向="水平"
                @drop="onColumnDrop($event)"
                ドラッグハンドルセレクター=".column-drag-handle"
        >
            <Draggable v-for="taskColumnList 内の列" :key="column.name">
                <div class="カードコンテナ">
                    <div class="カード列ヘッダー">
                        <span class="column-drag-handle">&#x2630;</span>
                        {{列名}}
                    </div>
                    <コンテナ
                            グループ名="col"
                            @drop="(e) => onCardDrop(column.id, e)"
                            :get-child-payload="getCardPayload(column.id)"
                            ドラッグクラス="カードゴースト"
                            ドロップクラス="カードゴーストドロップ"
                            :drop-placeholder="ドロッププレースホルダーオプション"
                            クラス="ドラッグ可能なコンテナ"
                    >
                        <Draggable v-for="task in column.list" :key="task.id">
                            <div class="タスクカード">
                                <div class="task-title">{{ タスク名 }}</div>
                                <div class="task-priority" :style="{ background: priorityMap[task.priority].color }">
                                    {{ priorityMap[task.priority].label }}
                                </div>
                            </div>
                        </ドラッグ可能>
                    </コンテナ>
                </div>
            </ドラッグ可能>
        </コンテナ>
    </div>
</テンプレート>

<スクリプト>
    「vue-smooth-dnd」から Container、Draggable をインポートします。

    const applyDrag = (arr, dragResult) => {
        const { removedIndex, addedIndex, payload } = dragResult
        console.log(削除されたインデックス、追加されたインデックス、ペイロード)
        if (removedIndex === null && addedIndex === null) は arr を返します。

        const 結果 = [...arr]
        itemToAdd = ペイロード

        if (削除されたインデックス !== null) {
            追加する項目 = result.splice(削除されたインデックス、1)[0]
        }

        追加されたインデックスが null の場合
            結果.splice(追加されたインデックス、0、追加する項目)
        }

        結果を返す
    }

    定数タスクリスト = [
        {
            名前: 'ホームページ',
            優先度: 'P1'、
            ステータス: 「開発中」、
            id: 1,
        },
        {
            名前: 「フローチャート開発」
            優先度: 'P3'、
            ステータス: 「審査待ち」、
            id: 2,
        },
        {
            名前: '統計グラフ表示'、
            優先度: 'P0'、
            ステータス: 「開発中」、
            id: 3,
        },
        {
            名前:「ファイル管理」
            優先度: 'P1'、
            ステータス: 「開発中」、
            id: 4,
        }
    ]

    const statusList = ['レビュー保留中'、'開発保留中'、'開発中'、'完了']

    const taskColumnList = statusList.map((ステータス、インデックス) => {
        戻る {
            名前: ステータス、
            リスト: taskList.filter(item => item.status === status),
            id: インデックス
        }
    })

    定数優先度マップ = {
        'P0': {
            ラベル:「最高品質」、
            色: '#ff5454',
        },
        'P1': {
            ラベル:「高品質」、
            色: '#ff9a00',
        },
        'P2': {
            ラベル: '中'、
            色: '#ffd139',
        },
        'P3': {
            ラベル: 'lower'、
            色: '#1ac7b5',
        },
    }

    エクスポートデフォルト{
        名前:「カード」
        コンポーネント: {コンテナ、ドラッグ可能},
        データ () {
            戻る {
                タスク列リスト、
                優先度マップ、
                ドロッププレースホルダーオプション: {
                    クラス名: 'ドロッププレビュー',
                    アニメーション期間: '150',
                    上部に表示: true
                }
            }
        },
        メソッド: {
            onColumnDrop (dropResult) {
                this.taskColumnList = applyDrag(this.taskColumnList、dropResult)
            },
            onCardDrop (列ID、ドロップ結果) {
                let { removedIndex, addedIndex, payload } = dropResult
                if (削除されたインデックス !== null || 追加されたインデックス !== null) {
                    定数列 = taskColumnList.find(p => p.id === columnId)
                    if (addedIndex !== null && payload) { // タスクステータスを更新 dropResult.payload = {
                            ...ペイロード、
                            ステータス: 列名、
                        }
                    }
                    列リスト = applyDrag(列リスト、dropResult)
                }
            },
            getCardPayload (列ID) {
                インデックスを返す =>
                    this.taskColumnList.find(p => p.id === columnId).list[インデックス]
            },
        }
    }
</スクリプト>


<スタイル>
    * {
        マージン: 0;
        パディング: 0;
        フォント ファミリ: 'Microsoft YaHei'、'PingFang SC'、'Helvetica Neue'、Helvetica、サンセリフ;
        行の高さ: 1.45;
        色: rgba(0,0,0,.65);
    }
    .カードシーン{
        ユーザー選択: なし;
        ディスプレイ: フレックス;
        高さ: 100%;
        マージン: 20px;
    }
    .カードコンテナ{
        ディスプレイ: フレックス;
        flex-direction: 列;
        幅: 260ピクセル;
        最小幅: 260px;
        境界線の半径: 12px;
        背景色: #edeff2;
        右マージン: 16px;
        高さ: calc(100vh - 40px);
    }
    .カード列ヘッダー {
        ディスプレイ: フレックス;
        高さ: 50px;
        マージン: 0 16px;
        アイテムの位置を中央揃えにします。
        フレックス収縮: 0;
        フォントの太さ: 500;
        フォントサイズ: 16px;
    }
    .ドラッグ可能なコンテナ{
        フレックス成長: 1;
        オーバーフロー:自動;
    }
    .列ドラッグハンドル{
        カーソル: 移動;
        パディング: 5px;
    }
    .タスクカード{
        マージン: 10px;
        背景色: 白;
        パディング: 15px 10px;
        境界線の半径: 8px;
        ボックスの影: 0 1px 2px 0 rgba(0, 0, 0, 0.12);
        カーソル: ポインタ;
        ディスプレイ: フレックス;
        コンテンツの両端揃え: スペースの間;
    }
    .タスクタイトル{
        色: #333333;
        フォントサイズ: 14px;
    }
    .タスク優先度{
        幅: 60ピクセル;
        行の高さ: 20px;
        境界線の半径: 12px;
        テキスト配置: 中央;
        色: #fff;
        フォントサイズ: 12px;
    }
    .カードゴースト{
        遷移: 変換 0.18 秒のイーズ;
        変換: rotateZ(5deg)
    }

    .カードゴーストドロップ{
        遷移: transform 0.18s イーズインアウト;
        変換: rotateZ(0deg)
    }

    .drop-preview {
        背景色: rgba(150, 150, 200, 0.1);
        境界線: 1px 破線 #abc;
        マージン: 5px;
    }
</スタイル>

効果

Vue のドラッグ可能なコンポーネントである Vue Smooth DnD の詳細な使用方法については、これで終わりです。Vue のドラッグ可能なコンポーネントに関するその他の関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue ドラッグ コンポーネント vuedraggable API オプションは、ボックス間の相互ドラッグと並べ替えを実現します。
  • 動的なページ構成機能を実現するVueドラッグコンポーネントリスト
  • Vueドラッグコンポーネントの使い方の詳しい説明
  • Vueドラッグコンポーネント開発例の詳しい説明
  • Vueは動的に生成されたコンポーネントをドラッグアンドドロップする要件を実装します
  • VueはSplitを使用して、ユニバーサルドラッグアンドスライドパーティションパネルコンポーネントをカプセル化します。
  • Vue がドラッグ プログレス バーのスライド コンポーネントを開発
  • vue draggable resizable はドラッグ可能なスケーリングのコンポーネント機能を実現します
  • Vue ドラッグ可能なコンポーネントを使用して、Vue プロジェクトでテーブル コンテンツのドラッグ アンド ドロップによる並べ替えを実装します。
  • VueコンポーネントDraggableはドラッグ機能を実装します
  • Vueでドラッグ可能なコンポーネントを実装する方法

<<:  Linuxでユーザーが所属するグループを変更する方法

>>:  MySQL 5.6.37 (zip) ダウンロード インストール 構成 グラフィック チュートリアル

推薦する

ラジオボタンと複数選択ボタンは画像を使用してスタイル設定されます

ラジオ ボタンや複数選択ボタンにスタイルを追加する方法や、ボタンを大きくする方法を尋ねる人を以前見か...

vue3 の setUp とリアクティブ関数の使用方法の詳細な説明

1. いつsetUpを実行するかvue3 ではメソッドを正常に使用できるようになったことは誰もが知っ...

MySQL における between の境界と範囲の説明

境界範囲間のmysql間の範囲は両側の境界値を含む例: 3 から 7 までの id は、id >...

最小限のルートファイルシステムを構築するためにbusyboxを移植するための詳細な手順

Busybox: 小さなコマンドが詰まったスイスアーミーナイフ。ステップ1: ディレクトリ構造を作成...

Nginx ルーティング転送とリバースプロキシロケーション構成の実装

Nginx を設定する 3 つの方法最初の方法は、位置一致部分を直接置き換える。 2 番目の pro...

Day.js をベースにした JavaScript での日付処理のよりエレガントな方法

目次day.js を使用する理由モーメントデイ.js day.js がなければどうなるでしょうか? ...

VMWare に CentOS 7.3 をインストールするグラフィカル チュートリアル

CentOS 7.3のインストール手順を図解しました。具体的な内容は次のとおりです。この記事では、v...

私のCSSアーキテクチャのコンセプト - それは人によって異なり、ベストなものはなく、適切なものだけがある

はじめに<br />私はフロントエンド分野でかなり長い間働いており、CSS分野でも長い間...

MongoDB データベースの状態を監視する Zabbix3.4 メソッド

Mongodb には db.serverStatus() コマンドがあり、これを使用して Mongo...

MySQLデータ復旧のさまざまな方法の概要

目次1. はじめに2. 直接回復2.1 mysqldumpバックアップの完全リカバリ2.2 xtra...

Vue プロジェクトで axios リクエストを使用する方法

目次1. インストール2. カプセル化に問題はない3. ファイルを作成する4. アドレス設定をリクエ...

ウェブデザインでよくある間違いのまとめ

Web ページを設計する過程で、デザイナーが間違いを犯すのは必然です。特に新人は、新しいアイデアを実...

Linux で crond ツールを使用してスケジュールされたタスクを作成する方法

序文Crond は Linux のスケジュール実行ツール (Windows のスケジュールされたタス...

HTML テーブルインライン形式の詳細な説明

インライン形式<colgroup>...</colgroup>属性名 属性値...