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のインストール手順

推薦する

CSS で要素フローティングとクリアフローティングを実装する方法

フローティングの基礎標準ドキュメント フローでは、要素は塊級元素と行內元素の 2 種類に分けられます...

Navicat で MySQL データベースのパスワードを変更する複数の方法

方法1: SET PASSWORDコマンドを使用するまずMySQLにログインします。フォーマット: ...

Linux/CentOS サーバー セキュリティ構成の一般ガイド

Linux はオープン システムです。インターネット上には、既成のプログラムやツールが多数存在します...

MySQL パーティション テーブルに関するパフォーマンス バグ

目次2. pt-pmapを使用したスタック分析3. このコラムのボトルネックポイントの分析4. パー...

指定フィールドによるMySQLカスタムリストのソートの実装

問題の説明ご存知のとおり、MySQL でフィールドを昇順に並べ替える SQL は次のとおりです (i...

MySQL 8.0.22 winx64 のインストールと設定のグラフィックチュートリアル

mysql 8.0.22 winx64のインストールと設定のグラフィックチュートリアルは参考までに、...

Mysqlツリー再帰クエリの実装方法

序文部門テーブルなどのデータベース内のツリー構造データの場合、部門のすべての従属部門または部門のすべ...

CSSスクロールバーのスタイルをカスタマイズする方法の詳細な説明

この記事では、CSS スクロールバー セレクターを紹介し、Webkit ブラウザーと IE ブラウザ...

MySql8.0バージョンに接続するMyBatisの設定問題について

mybatis を学習しているときにエラーが発生しました。エラーの内容は次のとおりです。データベース...

W3C チュートリアル (15): W3C SMIL アクティビティ

SMIL は、Web にタイミングとメディアの同期のサポートを追加します。 SMIL は、Web に...

CSS3アニメーションを使用した簡単な指クリックアニメーションの実装例

この記事では主に、CSS3 アニメーションで簡単な指クリックアニメーションを実装する例を紹介し、皆さ...

RR および RC 分離レベルでのインデックスとロックのテスト スクリプトのサンプル コード

基本概念現在の読み取りとスナップショットの読み取りMVCC では、読み取り操作はスナップショット読み...

Docker実践: Pythonアプリケーションのコンテナ化

1. はじめにコンテナはサンドボックス メカニズムを使用して相互に分離します。コンテナ内にデプロイさ...

MySQL セキュリティ管理の詳細

目次1. 順番に紹介する2. ユーザーを作成する3. ユーザーアカウントを削除する4. アクセス権5...

Ubuntuでネットワークルーティングテーブルを表示する方法

Linux におけるルーティングとルーティング テーブルとは何ですか?ルーティングのプロセスとは、ネ...