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) ダウンロード インストール 構成 グラフィック チュートリアル

推薦する

Vueでシングルサインオンを実装する方法のまとめ

最近プロジェクトが中断され、RageFrame の研究は一時的に終了しました。この記事では、シングル...

JavaScriptは、マウスが通過したときにドロップダウンボックスを表示するように実装します。

この記事では、マウスがドロップダウンボックスの上を通過するときにドロップダウンボックスを表示するため...

Flex プログラム Firefox で中国語を入力すると文字化けするバグ

Firefox の下位バージョンでは中国語の文字を入力できず、上位バージョンでは文字化けした文字が表...

MySQL のテーブル内のレコード数を制限する方法

目次1. トリガーソリューション2. パーティションテーブルソリューション3. 一般的な表領域ソリュ...

Docker Consul コンテナ サービスの更新と見つかった問題の概要

目次1. コンテナサービスの更新とDockerコンサルの検出1. サービス登録と検出とは何ですか? ...

SQL インジェクションの詳細

1. SQL インジェクションとは何ですか? SQL インジェクションは、入力パラメータに SQL ...

VMware 仮想マシンに Android x86 をインストールする方法

アプリをテストしたいが、それを携帯電話で実行したくない場合があります。この場合、仮想マシンを使用して...

MySQL DMLステートメントの使用に関する詳細な説明

序文:前回の記事では、注意深い学生であれば発見できたかもしれない DDL ステートメントの使用法を中...

Dapr を使用してマイクロサービスをゼロから簡素化する例

目次序文1. Dockerをインストールする2. Dapr CLIをインストールする3. Net6 ...

divは、自動入力スタイルをブロックする入力ボックスとして入力を使用せずにコンテンツを入力できます。

今日、私は公開用の動的なウィンドウ スタイルを設計しましたが、マウスで入力をクリックしたときにブラウ...

dockerでifconfigが利用できない問題を解決する

最近、docker を学習していたときに、docker コンテナ内のネットワーク状態を照会するために...

Docker Compose ワンクリック ELK デプロイ方式の実装

インストールFilebeat は、より軽量でより安全なため、Logstash-Forwarder に...

文字列から指定された文字を削除または抽出する JavaScript メソッド (非常によく使用されます)

目次1. 部分文字列() 2. サブストラクチャ() 3.インデックス() 4.最後のインデックス(...

Nginx の一般的な設定とテクニックの概要

序文この記事では、Nginx の一般的な、実用的で興味深い構成をいくつか紹介します。この記事を読んだ...

コード例を通してページ置換アルゴリズムの原理を理解する

ページ置換アルゴリズム: 本質は、限られたメモリをワイヤレス プロセスに対応できるようにすることです...