Vueカスタムテーブル列実装プロセス記録

Vueカスタムテーブル列実装プロセス記録

序文

フォームを使用して PC 側のプロジェクト、特に CRM システムを開発する場合、このような要件に頻繁に遭遇します。ユーザーは設定に応じて表示列をカスタマイズする必要があります。 要素の公式ドキュメントを確認しましたが、そのようなコンポーネントは見つからなかったので、そのようなニーズを開発するときに役立つことを期待して、単純なコンポーネントを手動でカプセル化しました。

レンダリング

具体的な効果図は以下のとおりです。

表示列をカスタマイズします(ドラッグ アンド ドロップして並べ替え、クリックして選択、もう一度クリックしてキャンセルできます)

ユーザーが設定したフィールドに従って各列を並べ替え/表示/非表示にする

setTable コンポーネント

まず、ドラッグ アンド ドロップによる並べ替えを実装するには、プラグインを使用する必要があります。

npm をインストール vuedraggable -S

具体的なコンポーネントコードは以下のとおりです。詳しいコメントはコード内に書かれているので、ここでは詳細は割愛します。 。

テーブルの設定

<テンプレート>
  <div>
    <el-dialog title="カスタム表示列" :visible.sync="dialogVisible" width="50%">
      <div class="メニューを選択メニューボックス">
        <p class="menus-title">ブロックをドラッグして表示順序を調整します</p>
        <div class="メニューコンテンツ">
          <ドラッグ可能な v-model="選択済み" @update="datadragEnd" :options="{アニメーション:500}">
            <遷移グループ>
              <div v-for="選択されたメニュー" :key="menu.field" class="drag-item item">{{menu.name}}</div>
            </トランジショングループ>
          </ドラッグ可能>
        </div>
      </div>
      <div class="メニューコンテナメニューボックス" v-if="フィールドの長さ">
        <p class="menus-title">表示列を選択</p>
        <div class="メニューコンテンツ">
          <div
            クラス="アイテム"
            :class="{active:menu.active}"
            v-for="フィールドのメニュー"
            :key="メニューフィールド"
            @click="onSelect(メニュー)"
          >{{メニュー名}}</div>
        </div>
      </div>
      <span slot="フッター" class="ダイアログフッター">
        <el-button @click="dialogVisible = false">キャンセル</el-button>
        <el-button type="primary" @click="onSave">OK</el-button>
      </span>
    </el-ダイアログ>
  </div>
</テンプレート>
<スクリプト>
「vuedraggable」から draggable をインポートします。
"@/api/user" から { getFields、setFields、getFieldControl } をインポートします。
エクスポートデフォルト{
  名前: "setTable"、
  挿入: ["リロード"],
  小道具: {
    型: 文字列、
  },
  コンポーネント:
    ドラッグ可能、
  },
  データ() {
    戻る {
      ダイアログ表示: false、
      fields: [], //すべてのメニューが選択されています: [], //選択されたメニュー};
  },
  時計:
    選択: {
      ハンドラ(古い値、新しい値) {
        if (this.fields.length === 0) {
          戻る;
        }
        新しいVal.map((i) => {
          this.fields.map((j) => {
            i.field === j.field の場合 {
              // 選択した配列に同じフィールドがすでに存在する場合、active は true になります。 Active は主に、すべてのメニューの選択/非選択スタイルを制御するために使用されます。j.active = true;
            }
          });
        });
      },
    },
  },
  マウント() {
    //ドラッグ時にFirefoxが新しいタブを開かないようにするには document.body.ondrop = function (event) {
      イベントをデフォルトにしない();
      イベントの伝播を停止します。
    };
  },
  メソッド: {
    非同期getData() {
      // すべてのメニューデータを取得する const { data: fields } = await getFields({
        型: this.types、
      });
      フィールド.map((アイテム) => {
        // サーバーはアクティブ フィールドを返さないため、選択されたスタイルを制御するには、各データにアクティブ フィールドを追加する必要があります。item.active = false;
      });
      this.fields = フィールド;
    },
    非同期getFields() {
      // ユーザーが選択したメニューを取得します。これにより、設定を再度開いたときに最後に選択したメニューがページに反映され、ユーザーが再度変更できるようになります。let fields = await getFieldControl({
        アカウントID: this.$store.state.user.token.account_id,
        ユーザーID: this.$store.state.user.token.userid,
        型: this.types、
      });
      this.$nextTick(() => {
        this.selected.push(...フィールドデータ);
      });
    },
    非同期onSave() {
      // 選択したメニューを保存する await setFields({
        アカウントID: this.$store.state.user.token.account_id,
        ユーザーID: this.$store.state.user.token.userid,
        型: this.types、
        コンテンツ: this.selected、
      });
      this.reload(); //ページを更新する},
    非同期オープン(){
      // 設定ウィンドウを開いたときにデータをクリアし、最新のデータを再度要求します。this.fields = [];
      this.selected = [];
      this.dialogVisible = true;
      this.getData() を待機します。
      this.getFields() を待機します。
    },
    onSelect(アイテム) {
      // 選択されたメニューに選択されたメニューがあるかどうかを判定する let findex = this.selected.findIndex((i) => {
        item.field === i.field を返します。
      });
      (検索インデックス === -1)の場合{
        // メニューに選択された項目がない場合は、最後の項目に追加します this.selected.push(item);
      } それ以外 {
        // すでに選択されている場合は、クリックすると選択が解除され、選択されたスタイルを変更するには active を false に設定する必要があります。item.active = false;
        this.selected.splice(findex, 1);
      }
    },
    データドラッグ終了(evt) {
      // ドラッグソート evt.preventDefault();
    },
  },
};
</スクリプト>
<style lang="scss" スコープ>
/* すべてのメニュー */
.メニューコンテナ{
  上マージン: 20px;
  .メニューコンテンツ{
    。アイテム {
      色: #575757;
      背景: rgba(238, 238, 238, 1);
      境界線: 1px実線 rgba(220, 220, 220, 1);
      境界線の半径: 2px 0px 0px 2px;
    }
  }
}
/* メニューの一般的なスタイル*/
.メニューボックス{
  .メニュータイトル{
    上マージン: 10px;
    行の高さ: 32px;
  }
  .メニューコンテンツ{
    ディスプレイ: フレックス;
    flex-wrap: ラップ;
    。アイテム {
      カーソル: ポインタ;
      ディスプレイ: インラインフレックス;
      アイテムの位置を中央揃えにします。
      コンテンツの中央揃え: 中央;
      パディング: 8px;
      マージン: 10px;
      境界線の半径: 3px;
    }
    。アクティブ {
      色: #fff;
      背景: rgba(72, 153, 229, 1);
      境界線の半径: 2px 0px 0px 2px;
    }
  }
}

/* 選択されたメニュー */
.select-menus {
  .メニューコンテンツ{
    。アイテム {
      マージン: 0px;
      境界線の半径: 0;
      背景: rgba(255, 255, 255, 1);
      境界線: 1px実線 rgba(220, 220, 220, 1);
    }
  }
}
</スタイル>

使用

具体的な使い方は以下の通りです。ここでは皆さんに誤解を与えないよう、不要な業務コードは隠して、コアとなる実装コードのみを掲載しています。

<テンプレート>
  <div>
    <el-テーブル
      ref="複数のテーブル"
      :data="テーブルデータ"
      高さ="60vh"
      :row-class-name="テーブル行クラス名"
      @selection-change="選択変更処理"
      @row-click="handleRead"
    >
      <el-table-column type="selection" min-width="55px;"></el-table-column>
      <template v-for="(item,index) フィールド">
        <el-テーブル列
          v-if="item.field==='名前'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='性別'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="8%;"
          オーバーフローツールチップを表示
        >
          <template slot-scope="scope">{{scope.row.gender===1?'男':'女'}}</template>
        </el-table-column>
        <el-テーブル列
          v-if="item.field==='corp_full_name'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="14%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='corp_name'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="12%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='up_date'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="14%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='位置'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='remark_mobiles'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="14%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='source_name'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='アドレス'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='detail_address'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='説明'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='コメント'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='recordContent'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="14%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='owner_name'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
        <el-テーブル列
          v-if="item.field==='follow_time'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="8%;"
          オーバーフローツールチップを表示
        >
          <テンプレート スロット スコープ="スコープ">
            <div v-if="scope.row.follow_time===scope.row.createtime">なし</div>
            <div v-else>{{scope.row.follow_time | formatDate}}</div>
          </テンプレート>
        </el-table-column>
        <el-テーブル列
          v-if="item.field==='next_follow_time'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="8%;"
          オーバーフローツールチップを表示
        >
          <テンプレート スロット スコープ="スコープ">
            <div v-if="scope.row.next_follow_time===0">なし</div>
            <div v-else>{{scope.row.next_follow_time | formatDate}}</div>
          </テンプレート>
        </el-table-column>
        <el-テーブル列
          v-if="item.field==='createtime'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="8%;"
          オーバーフローツールチップを表示
        >
          <テンプレート スロット スコープ="スコープ">
            <div>{{scope.row.createtime | formatDate}}</div>
          </テンプレート>
        </el-table-column>
        <el-テーブル列
          v-if="item.field==='更新時間'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="8%;"
          オーバーフローツールチップを表示
        >
          <テンプレート スロット スコープ="スコープ">
            <div>{{scope.row.updatetime | formatDate}}</div>
          </テンプレート>
        </el-table-column>
        <el-テーブル列
          v-if="item.field==='is_record'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        >
          <テンプレート スロット スコープ="スコープ">
            <div>{{scope.row.is_record === 0 ? 'フォローアップされていません' : 'すでにフォローアップされています' }}</div>
          </テンプレート>
        </el-table-column>
        <el-テーブル列
          v-if="item.field==='if_record'"
          :key="インデックス"
          :prop="アイテム.フィールド"
          :label="アイテム名"
          最小幅="10%;"
          オーバーフローツールチップを表示
        </el-table-column> ...
      </テンプレート>
      <el-table-column label="操作" min-width="8%;">
        <テンプレート スロット スコープ="スコープ">
          <el-button @click="handleRead(scope.row)" type="text">詳細</​​el-button>
        </テンプレート>
      </el-table-column>
      <el-table-column align="right" min-width="4%;">
        <テンプレートスロット="ヘッダー">
          <i class="iconfont icongengduo" @click="onMore"></i>
        </テンプレート>
      </el-table-column>
    </el-table>
    <set-table ref="setting" types="リード"></set-table>
  </div>
</テンプレート>

<スクリプト>
「@/components/setTable」からsetTableをインポートします。
"@/api/user" から getFieldControl をインポートします。
エクスポートデフォルト{
  名前: 「手がかり」、
  コンポーネント:
    テーブルの設定、
  },
  データ() {
    戻る {
      フィールド: [],
    };
  },
  非同期マウント() {
    this.getFields() を待機します。
    this.clues();
  },
  メソッド: {
    非同期getFields() {
      フィールドをawait getFieldControl({
        アカウントID: this.$store.state.user.token.account_id,
        ユーザーID: this.$store.state.user.token.userid,
        タイプ: 「リード」、
      });
      フィールドをデータに格納します。
    },
    オンモア() {
      this.$refs.setting.open();
    },
  },
};
</スクリプト>

実際、ここで固定の列幅を設定したり、サーバーを通じて特定のサイズを返したりすることもできます。このようにすると、多くの if ステートメントを書く必要がなくなり、より便利で簡潔になります。

結論

実際、この要件を最初に受け取ったときは、サーバーから返されるさまざまなフィールドに応じてフォームの列をドラッグして並べ替える必要があったため、非常に複雑に感じました。 しかし、全体的には思ったほど面倒ではありませんでした。 必要に迫られたときは、あまり考えすぎず、まずは試してみると、思ったほど難しくないかもしれません。

これで、vue カスタム テーブル列に関するこの記事は終了です。より関連性の高い vue カスタム テーブル列については、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • VUE2.0+ElementUI2.0 テーブル el-table はヘッダー拡張 el-tooltip を実装します
  • Vue+Element カスタム垂直テーブルヘッダーチュートリアル
  • Vue はカスタム テーブル ツール拡張を実装します

<<:  データベースSQL SELECTクエリの仕組み

>>:  Linux 上での MySQL データベースのインストールと Java プロジェクトの構成に関する詳細なグラフィック説明

推薦する

Linux 型バージョン メモリ ディスク クエリ コマンド紹介

1. まず、Linux システムのバージョン内容について概要を説明します。 1. カーネルバージョン...

mysqlにコメント情報を追加する実装

序文最近、MySQL に関するメモをいくつか尋ねる人がいたので、ブログ記事を書かなければなりません。...

HTML テーブルタグチュートリアル (21): 行の境界線の色属性 BORDERCOLOR

テーブルを美しくするために、行ごとに異なる境界線の色を設定できます。基本的な構文<TR 境界線...

CSSページ下部固定を実現する8つの方法の詳細な説明

ページを書いているときに、ページの内容が小さくてフッターがページの真ん中に留まってしまうといった状況...

nginx を使用してカナリアリリースをシミュレートする方法

この記事では、ブルーグリーン デプロイメントと、nginx を使用してカナリア リリースを最も簡単な...

Vueストレージにはブール値のソリューションが含まれています

Vueはブール値でストレージを保存します今日、問題に遭遇しました。バックグラウンドから返された真偽の...

ページにスクロールバーが表示されたときに、スクロールバーがページ幅に影響しないようにする方法

本体の幅をウィンドウの幅に設定します(次のスクリプトで制御されます) $("body&qu...

MySQL自動シャットダウン問題への対処の実践記録

最近、あるプロジェクトを手伝ったのですが、MySQL マシンがしばらくすると自動的に停止し続けました...

露滴アニメーション効果を実装するための Three.js サンプル コード

序文みなさんこんにちは。CSS ウィザードの alphardex です。この記事では、three.j...

JavaScriptでページスクロールアニメーションを実装する

目次レイアウトを作成するCSSスタイルを追加するJavaScript で要素を操作する対象要素を取得...

nginxリバースプロキシのyum設定の詳細な手順

パート0 背景社内のイントラネットサーバーは直接インターネットにアクセスすることはできませんが、外部...

MySQL 5.7 データベースのインストール手順の個人的な要約

1.mysql-5.7.19-winx64.zip(これは無料のインストールバージョンで、約318 ...

Linux で大きなファイルの内容を消去または削除する 5 つの方法

Linux ターミナルでファイルを操作しているときに、Linux コマンドライン エディターでファイ...

Javascript における非同期待機の詳細な理解

この記事では、async/await がすべての JavaScript 開発者にとって非同期プログラ...

Dockerにelasticsearchとkibanaをインストールする方法

Elasticsearchは現在非常に人気があり、多くの企業が利用しているため、esを知らないと軽蔑...