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 プロジェクトの構成に関する詳細なグラフィック説明

推薦する

Web プロジェクト開発 JS 機能の手ぶれ補正とスロットリングのサンプル コード

目次安定導入手ぶれ補正シーン1(マウスの動き込み)手ぶれ補正シーン2(キーボードのキー)関数のスロッ...

Svelte の Defer Transition を Vue で実装する方法

最近、Rich Harris の <Rethinking Reactivity> ビデオ...

require loaderの実装原理の深い理解

序文Node は新しいプログラミング言語ではなく、JavaScript のランタイムに過ぎないとよく...

HTML+CSS マージテーブル境界線サンプルコード

table タグと td タグに境界線を追加すると、デフォルトでは次のように二重境界線が使用されます...

JavaScript カラービューア

この記事では、カラービューアを実装するためのJavaScriptの具体的なコードを参考までに紹介しま...

JavaScriptタイマーの詳細な説明

目次簡単な紹介間隔の設定説明するパラメータ戻り値使用法タイムアウトの設定説明するパラメータ使用法:タ...

複数のドメイン名に対する Nginx リバース プロキシを使用した HTTP および HTTPS サービスの実装

現在、Nginx は、Web サービスを提供するために、Windows ベースの IIS と Lin...

Git サーバーを使用してデバッグ ブランチを表示し、修正する方法を 1 日 1 分で学習します。

デバッグブランチプロジェクトの通常の開発中に、以前にリリースされたバージョンにバグがある場合がありま...

純粋な CSS で DIV サスペンションを実装するサンプル コード (固定位置)

DIV フローティング効果 (固定位置) は CSS のみで実装されており、IE8、360、Fir...

Linux システムで jmeter を実行し、ローカル メモリを最適化する方法の詳細な説明

1. Linuxシステムにクロスシステムファイル転送ツールをインストールするルートユーザーのルートデ...

jQuery でダイナミックなパーティクル効果を実現

この記事では、動的なパーティクル効果を実現するためのjQueryの具体的なコードを参考までに紹介しま...

HTMLページ埋め込み動画とJSコントロール切り替え動画例の詳しい説明

まず、ページにビデオを埋め込むための HTML コードは次のとおりです。コードをコピーコードは次のと...

js での typeof の使い方を理解するための記事

目次ベース戻り値の型文字列とブール値数値とbigintシンボル未定義関数物体他のよくある質問参照エラ...

HTMLでは、全体的なスタイルとレイアウトを崩さずに、部分的に強制スクロールバーを使用できます。

まずはエフェクト画像を投稿します:全体的なスタイルとレイアウトが崩れないように、スクロール バーがロ...

Dockerfile に基づいて Tomcat イメージを構築する方法

Dockerfile は Docker イメージを構築するために使用されるファイルです。コマンドパラ...