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

推薦する

CSSとJSでロマンチックな流星群アニメーションを実現

1. レンダリング 2. ソースコードhtml < 本文 > < div クラス ...

ウェブページ作成時に標準 HTML コードを使用する際のポイント

<br />多くのウェブサイト デザイナーが犯す最も一般的な間違いは、ウェブページが I...

画像拡大鏡効果のJSバージョン

この記事では、画像拡大鏡効果を実現するためのJSの具体的なコードを参考までに紹介します。具体的な内容...

VueのRender関数

目次1. ノード、ツリー、仮想DOM 2. 仮想DOM 2.1 データオブジェクトの詳細2.2 制約...

MySQL 集計関数のソート

目次MySQL 結果のソート - 集計関数環境クエリ結果の並べ替えクエリのグループ化と集約生徒の平均...

XHTML と CSS の Web ページ作成の問題に対する解決策

XHTML CSS ページ制作中に遭遇する問題の解決策は、解決策と呼ぶには少々大げさです。せいぜい、...

Maven プロジェクトのリモート デプロイメント && Tomcat を使用してデータベース接続を構成する方法

1つ。 tomcat を使用したリモート展開1.1 発生した問題:プロジェクトでは、サードパーティの...

CSSレイアウトにおけるフロート属性と位置属性の違い

CSS レイアウト - position プロパティposition 属性は、要素に適用する配置方法...

MySQL マスター スレーブ データが矛盾しています。プロンプト: Slave_SQL_Running: 解決策はありません

この記事では、MySQL マスターとスレーブ データ間の不一致の解決方法と、プロンプト「Slave_...

MySQL データ型における DECIMAL の使用法の詳細な説明

MySQL データ型における DECIMAL の使用法の詳細な説明MySQL のデータ型には、INT...

dubbo での Zookeeper リクエストのタイムアウト問題: mysql8.0.15 に接続する mybatis+spring の構成

ここ2日間Javaを復習するつもりなので、練習にdubboを使ってショッピングモールプロジェクトを書...

この記事はVueのライフサイクルを理解するのに役立ちます

目次1. beforeCreate & created 2. マウント前とマウント済み3. ...

Vue カプセル化 TabBar コンポーネントの完全なステップ記録

目次実装のアイデア:ステップ 1: TabBar と TabBarItem のコンポーネント カプセ...

英語の単語の出現頻度を数えるtrコマンドの魔法

置換を削除したり文字列を削除したりできる tr コマンドは、誰もがよく知っています。 英語では、英語...

MySQL トランザクション、分離レベル、ロックの使用例の分析

この記事では、例を使用して、MySQL トランザクション、分離レベル、およびロックの使用について説明...