Vueは動的に生成されたコンポーネントをドラッグアンドドロップする要件を実装します

Vueは動的に生成されたコンポーネントをドラッグアンドドロップする要件を実装します

製品要件

製品要件会議の後、私たちはある要件に遭遇しました。まず、ページが 2 つの列に分割され、データ コンポーネントが左側に表示され、ドラッグ アンド ドロップによる並べ替えがサポートされ、ボタンをクリックしてコンポーネントをクリアできるというものでした。右側では、コンポーネントのサムネイルを左側にドラッグして新しいコンポーネントを生成することができます。

アイデア

動的に生成されるコンポーネントの場合、そのコンポーネントを関数に入れて返すことができるように、毎回新しいコンポーネントを生成する必要があります。 JSX で関数を呼び出すと、関数の呼び出しごとにまったく新しいコンポーネントが返されます。これは React では非常に簡単ですが、Vue ではコンポーネントを直接返すことは不可能です。この return の書き方は Vue には適していませんが、考え方が非常に正しいことは否定できないので、別の書き方を検討する必要があります。動的に生成されるコンポーネントに関しては、データを使用してコンポーネントの生成を駆動する必要があります。ドラッグ コンポーネントのソートには、ドラッグ ライブラリを使用するだけです。 !

問題

  1. ライブラリ選択をドラッグ
  2. コンポーネントを生成する方法
  3. データに基づいてコンポーネントを動的に生成する

ライブラリ選択をドラッグ

ドラッグ ライブラリには、プロジェクト内に存在するドラッグ ライブラリである Vue.Draggable を選択しました。ここをクリックすると、Start 14.9K が表示されます。これはかなり良いです。 Vue プロジェクトでこのドラッグ ライブラリを使用しない場合は、この記事のデザイン アイデアを参照できます。

コンポーネントを生成する方法

ここでは Vue.extend() を使用します。使い方がわからない場合は、この記事の Vue.extend を学習する前に公式ドキュメントを確認してください。 次に、コンポーネントを作成するためのコードを記述する js ファイルを作成します。

コンポーネントを生成する

/* generateComponents.js ファイル名 */

「vue」からVueをインポートします。

// コンポーネントを動的に生成する場合は、まずこのファイルをインポートします。
「./components/TestCom1.vue」からcomponents1をインポートします。
「./components/TestCom2.vue」からcomponents2をインポートします。

// コンポーネント名とコンポーネント間の対応するマップを作成します
定数comMap = {
  コンポーネント1、
  コンポーネント2、
};

// コンポーネントを生成するために必要なコンポーネント名と、コンポーネントに渡すプロパティとイベントを受け取ります。const ReturnNewCom = function ({ props, on }) {
  定数{
    comItem: {名前},
  } = プロパティ;
  const newComponent = Vue.extend({
    レンダリング(要素を作成) {
      // 渡されたコンポーネント名を使用して、レンダリングするコンポーネントを決定します。
      createElement(comMap[name], { を返します。
        小道具、
        の上、
      });
    },
  });
  新しい newComponent() を返します。
};

デフォルトのReturnNewComをエクスポートします。

コンポーネント

ここでは、このデモを示すために、components1.vue と components2.vue という 2 つのコンポーネントを記述します。

/*components1.vue*/
<テンプレート>
  <div class="widget-wrapper">
    <header class="header">{{ comDetail.name }}--{{ comDetail.id }}</header>
    <h1>クエリ条件: {{ queryObj }}</h1>
    <button @click="handleDelete">クリア</button>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  データ() {
    戻る {
      comDetail: this.comItem、
      _queryObj: this.queryObj、
    };
  },
  小道具: {
    comアイテム: {
      タイプ: オブジェクト、
      デフォルト() {
        戻る {
          id: 0,
          名前: ""、
        };
      },
    },
    クエリオブジェクト: {
      //親コンポーネントから渡された選択条件を受け取ることができます。オブジェクトである必要があります
      タイプ: オブジェクト、
      デフォルト() {
        // デフォルトのクエリ条件を定義します。
        戻る {
          番号: 0,
        };
      },
    },
  },
  時計:
    comItem(val) {
      this.comDetail = val;
      戻り値:
    },
    クエリオブジェクト(val) {
      this._queryObj = val;
      戻り値:
    },
  },
  作成された() {
    console.log("データ -> this.comItem", this.comItem);
  },
  メソッド: {
    削除処理() {
      // コンポーネントメソッドを削除します this.$el.remove();
      // 親コンポーネントの関数を呼び出します。親コンポーネントの leftComList 配列のデータを変更します。
      this.$emit("handleDelete", this.comDetail);
    },
  },
};
</スクリプト>
<スタイルスコープ>
.ウィジェットラッパー{
  背景: #ff7b7b;
  境界線の半径: 12px;
  オーバーフロー: 非表示;
  幅: 200ピクセル;
}
.ヘッダー{
  高さ: 50px;
  パディング: 0 15px;
}
</スタイル>

実際、components2.vue ファイルのコードは components1.vue ファイルのコードと似ています。唯一の違いは背景色です。

データ駆動による動的コンポーネントの生成

次に、ドラッグ ライブラリ Vue.Draggable を使用してデータをドラッグおよび変更する必要があります。 App.vue ファイルに直接書き込むことができます。

/* アプリ.vue */
<テンプレート>
  <div class="dragCom">
    <h1>{{ 左ComList }}</h1>
    <button @click="queryObj.num++">クエリ条件を変更する</button>
    <div class="body">
      <div class="left">
        <ドラッグ可能なクラス="left" :list="leftComList" :group="'people'">
          <div
            ref="comBody"
            v-for="({ name, id }, index) が leftComList 内にあります"
            :key="id"
            クラス="comCard"
          >
            <!-- leftComList 配列をループし、そのデータを使用してコンポーネントをレンダリングします。 
            動的に生成された配列をこの DOM 要素に追加します。 -->
            {{
              ハンドルAddCom({
                プロパティ: { comItem: { 名前、ID }、クエリオブジェクト }、
                索引、
              })
            }}
          </div>
        </ドラッグ可能>
      </div>
      <div class="right">
        <ドラッグ可能
          クラス="ドラッグエリア"
          :list="右ComList"
          :group="{ name: 'people', pull: 'clone', put: false }"
          :clone="ハンドルCloneDog"
        >
          <div class="card" v-for="rightComList 内の要素" :key="element.id">
            {{要素名}}
          </div>
          <!-- 右側のカードデータ、rightComList配列オブジェクト内の名前はgenerateComponents.jsに対応します
          ComMap 内の属性 -->
        </ドラッグ可能>
      </div>
    </div>
  </div>
</テンプレート>

<スクリプト>
「vuedraggable」から draggable をインポートします。
「./generateComponents」からCreateComをインポートします。
エクスポートデフォルト{
  コンポーネント:
    ドラッグ可能、
  },
  データ() {
    戻る {
      右ComList: [
        {
          id: Math.random(),
          名前: "components1",
        },
        {
          id: Math.random(),
          名前: "components2",
        },
      ]、
      leftComList: [], //動的に生成されたコンポーネントを駆動するデータを格納します。
      comMap: new Map(), // 主な機能は、コンポーネントが class="comCard" の DOM にレンダリングされるかどうかを記録することです。
      // レンダリングされると、これ以上子要素を追加できなくなります。
      クエリオブジェクト: {
        // メイン関数は、クエリ条件をサブコンポーネント num: 0 に渡すことです。
      },
    };
  },
  破棄する前に() {
    // 記録されたデータをクリアします this.comMap.clear();
  },
  メソッド: {
    handleAddCom({ インデックス、 on = {}、 props = { comItem: { 名前: "", id: 0 } } }) {
      定数{
        comItem: { id },
      } = プロパティ;
      this.$nextTick(() => {
        // このノードの子ノードの長さを取得します。const childNodesLength = this.$refs.comBody[index].childNodes.length;
        // DOM 配列 comBody の長さを取得します。const comLine = this.$refs.comBody.length;
        if (!this.comMap.get(id)) {
          // コンポーネントがレンダリングされていない場合 // 1. CreateCom メソッドを呼び出してコンポーネントを作成します。 そして、propsとイベントを渡します。const com = CreateCom({
            小道具、
            の上: {
              ハンドル削除: this.handleDeleteCom、
              ...の上、
            },
          });
          // 2. コンポーネント com.$mount() を生成します。
          子ノードの長さが 2 の場合
            // 2 つのコンポーネントの間に追加する場合。次に、新しく生成されたコンポーネントの DOM の位置を変更し、中央に配置します。
            // 最終コンポーネントDOMを正しい場所に追加します this.$refs.comBody.splice(
              索引、
              0,
              this.$refs.comBody[comLine - 1]
            );
          }
          // 3. 生成されたコンポーネントを DOM に追加します。
          this.$refs.comBody[index].appendChild(com.$el);
          // 4. コンポーネントがレンダリングを実装していることを記録します。
          this.comMap.set(id, true);
        } それ以外 {
          // この位置のコンポーネントはレンダリングされているため、再度レンダリングする必要はなく、そのまま返します。
        }
      });
    },
    handleDeleteCom({id}) {
      // コンポーネント ID に従ってデータを削除するために子コンポーネントに渡されるメソッド const index = this.leftComList.findIndex((item) => item.id === id);
      if (~インデックス) {
        // この ID を持つコンポーネントが存在する場合は削除します this.leftComList.splice(index, 1);
      }
    },
    ハンドルクローンドッグ(アイテム) {
      // leftComList配列にデータを追加する return {
        ...アイテム、
        id: Math.random(),
      };
    },
  },
};
</スクリプト>

<スタイル>
.dragCom{
  フォントファミリー: Avenir、Helvetica、Arial、sans-serif;
  -webkit-font-smoothing: アンチエイリアス;
  -moz-osx-font-smoothing: グレースケール;
  テキスト配置: 中央;
  色: #2c3e50;
  上マージン: 60px;
}
。体 {
  幅: 100%;
  高さ: 800ピクセル;
  ディスプレイ: フレックス;
  コンテンツの両端揃え: スペースの間;
}
。左 {
  フレックス: 1;
  高さ: 800ピクセル;
  境界線: 1px ピンク
}
。右 {
  幅: 20%;
  高さ: 800ピクセル;
}
.カード{
  高さ: 50px;
  背景色: #40cec7;
  マージン: 12px 0;
  フォントサイズ: 12px;
  行の高さ: 50px;
  カーソル: ポインタ;
}
.comカード{
  マージン: 12px;
  表示: インラインブロック;
}
</スタイル>


これにより、動的なコンポーネントのレンダリングとドラッグソートが可能になります。

効果

ソースコード

試してみたい学生は、この記事のソースコードをgithubからダウンロードできます。

上記は、Vue のドラッグと動的コンポーネント生成の要件の詳細な内容です。Vue のドラッグと動的コンポーネント生成の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

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

<<:  Centos6でgitlabを構築する方法

>>:  LinuxでのMySQLのインストール手順

推薦する

Alipay の Java 決済インターフェースを開発するための詳細な手順

目次最初のステップステップ2ステップ3ステップ4 Alipay 決済インターフェースへの接続に関する...

CSS3 画像の境界線を学ぶのに役立つ記事

CSS3 border-image プロパティを使用すると、要素の周囲に画像の境界線を設定できます。...

Nginx 外部ネットワーク アクセス イントラネット サイト構成操作

背景:サイトはフロントエンドとバックエンドから分離されています: vue+springbootフロン...

Layuiテーブル行のデータを動的に編集する

目次序文スタイル機能説明初期化コードイベントリスナーの追加リスナーツールバーモニターテーブル行ツール...

JavaScript で二分探索木を実装する

JavaScriptでの検索二分木実装は参考までに。具体的な内容は以下のとおりです。バイナリ検索木 ...

VPSサーバーでよく使われるパフォーマンステストスクリプトの概要

これは、VPS サーバー用の一般的なワンクリック パフォーマンス テスト スクリプトです。マシンの構...

HTML はテキストの外側に省略記号を表示します...テキストオーバーフローによって実装されます

div または span に同時に CSS を適用する必要があります。コードをコピーコードは次のとお...

CSSで半透明の背景色を実現する2つの方法について簡単に説明します。

ページをレイアウトする際、ユーザーに異なる視覚効果を与えるために、div の背景色を半透明の状態に設...

vsFTP 3.0.3 のコンパイルとインストールの詳細な分析

脆弱性の詳細VSFTP は、GPL に基づいてリリースされた Unix ライクなシステムで使用される...

MySql 5.7.17 無料インストール構成チュートリアルの詳細な説明

1. mysql-5.7.17-winx64.zip インストール パッケージをダウンロードします ...

JS変数ストレージのディープコピーとシャローコピーの詳しい説明

目次可変タイプとストレージスペーススタックメモリとヒープメモリ基本的なデータ型参照タイプグラフィック...

CentOS7でMySQL 5.7をアンインストールする方法

MySQLに何がインストールされているか確認する rpm -qa | grep -i mysql n...

Vueプロジェクトでコンポーネントをカプセル化する簡単な手順

目次序文Toastコンポーネントをカプセル化する方法ユースケース具体的な実装要約する序文ビジネスが発...

MySQLデータベースのマスタースレーブ同期の実際のプロセスの詳細な説明

目次インストール環境の説明MySQLデータベースサービスをインストールするメインライブラリを構成する...

DIVのぼかし機能を実装する方法

マウスを動かしたときにDIVが消えるように手ぶれ補正を使用するdiv タグ自体は onblur イベ...