基於element-ui進行二次封裝的表格組件

来源:https://www.cnblogs.com/zz151/archive/2023/03/09/17198979.html
-Advertisement-
Play Games

<!-- * @description 表格組件 * @fileName TableList.vue * @authorQ * @date 2021/05/15 15:13:45 --> <template> <div class="table-container"> <el-table v-if= ...


<!--
* @description 表格組件
* @fileName TableList.vue
* @authorQ
* @date 2021/05/15 15:13:45
-->
<template>
  <div class="table-container">
    <el-table
      v-if="showTable"
      ref="filterTable"
      :span-method="spanName?objectSpanMethod:null"
      :data="data"
      :show-summary="showSummary.show ? showSummary.show : null"
      :summary-method="showSummary.show ? summaryMethod : null"
      :sum-text="showSummary.sumText ? showSummary.sumText : null"
      @filter-change="handleFilterChange"
      :border="border"
      :stripe="stripe"
      empty-text="暫無數據"
      style="width: 100%"
      :show-header="showHeader"
      :tooltip-effect="tooltipTheme"
      @selection-change="handleSelectionChange"
    >
      <!-- 選擇框列 -->
      <el-table-column
        v-if="selection"
        type="selection"
        :align="'center'"
      ></el-table-column>
      <!-- 排序列 -->
      <el-table-column
        v-if="indexShow"
        width="100"
        label="序號"
        :align="'center'"
      >
        <template slot-scope="scope">
          <div>
            <span>{{ scope.$index + 1 }}</span>
          </div>
        </template>
      </el-table-column>

      <template v-for="(item, index) in columns">
        <!-- 特殊列處理 -->
        <template v-if="item.render">
          <!-- visible 是否顯示該列 -->
          <el-table-column
            v-if="item.visible"
            :filters="item.filters ? item.filters : null"
            :column-key="item.prop"
            :key="index"
            :prop="item.prop ? item.prop : null"
            :align="item.align ? item.align : null"
            :fixed="item.fixed ? item.fixed : null"
            :label="item.label ? item.label : null"
            :show-overflow-tooltip="item.tooltip"
            :class-name="className"
            :sortable="item.sortable ? item.sortable : false"
            :width="item.width ? item.width : null"
          >
            <!-- 多級表頭 -->
            <template v-if="item.children && item.children.length > 0">
              <div v-for="(item1, index1) in item.children" :key="index1">
                <el-table-column
                  :key="index1"
                  :filters="item.filters ? item.filters : null"
                  :column-key="item.prop"
                  :prop="item1.prop ? item1.prop : null"
                  :align="item1.align ? item1.align : null"
                  :fixed="item1.fixed ? item1.fixed : null"
                  :label="item1.label ? item1.label : null"
                  :show-overflow-tooltip="item1.tooltip"
                  :class-name="className"
                  :sortable="item1.sortable ? item1.sortable : false"
                  :width="item1.width ? item1.width : null"
                >
                  <exSlot
                    :render="item1.render"
                    :row="scope.row"
                    :index1="scope.$index"
                    :column="item1"
                  />
                </el-table-column>
              </div>
            </template>
            <!-- 不是多級表頭 -->
            <template slot-scope="scope">
              <exSlot
                :render="item.render"
                :row="scope.row"
                :index="scope.$index"
                :column="item"
              />
            </template>
          </el-table-column>
        </template>

        <!-- 正常列 -->
        <template v-else>
          <!-- visible 是否顯示該列 -->
          <el-table-column
            v-if="item.visible"
            :key="index"
            :column-key="item.prop"
            :filters="item.filters ? item.filters : null"
            :prop="item.prop ? item.prop : null"
            :align="item.align ? item.align : null"
            :fixed="item.fixed ? item.fixed : null"
            :label="item.label ? item.label : null"
            :class-name="className"
            :show-overflow-tooltip="item.tooltip"
            :sortable="item.sortable ? item.sortable : false"
            :width="item.width ? item.width : null"
          >
            <!-- 多級表頭 -->
            <template v-if="item.children && item.children.length > 0">
              <template v-for="(item1, index1) in item.children">
                <el-table-column
                  :prop="item1.prop ? item1.prop : null"
                  :column-key="item.prop"
                  :filters="item.filters ? item.filters : null"
                  :align="item1.align ? item1.align : null"
                  :fixed="item1.fixed ? item1.fixed : null"
                  :label="item1.label ? item1.label : null"
                  :show-overflow-tooltip="item1.tooltip"
                  :class-name="className"
                  :sortable="item1.sortable ? item1.sortable : false"
                  :width="item1.width ? item1.width : null"
                >
                  <template slot-scope="scope">
                    <span v-html="formatter(scope.row[item1.prop])"></span>
                  </template>
                </el-table-column>
              </template>
            </template>
            <template slot-scope="scope">
              <!-- 字典處理 -->
              <template v-if="item.dict">
                <!-- 判斷原始數據是否有效,有效轉為字典數據,無效則轉為--占位符 -->
                <span
                  v-if="!scope.row[item.prop]"
                  v-html="formatter(scope.row[item.prop])"
                ></span>
                <dict-tag
                  v-else
                  :options="dict.type[item.prop]"
                  :value="scope.row[item.prop]"
                />
              </template>
              <!-- 時間格式化 -->
              <span v-else-if="item.time">{{
                parseTime(scope.row[item.prop], "{y}-{m}-{d}")
              }}</span>
              <!-- 不做處理 -->
              <span v-else v-html="formatter(scope.row[item.prop])"></span>
            </template>
          </el-table-column>
        </template>
      </template>

      <!-- 操作列 -->
      <el-table-column
        v-if="isEdit === true"
        label="操作"
        :align="'center'"
        width="200"
        :fixed="fixed"
      >
        <template slot-scope="scope">
          <slot name="editSlot">
            <template>
              <el-button type="primary" @click="editClick(scope.row)"
                >編輯</el-button
              >
              <el-button type="danger" @click="deleteClick(scope.row)"
                >刪除</el-button
              >
            </template>
          </slot>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      :style="{ float: `${paginationPosition}` }"
      v-if="pagination"
      :background="background"
      :current-page.sync="currentPage"
      :page-size.sync="currentSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
// 自定義內容的組件
var exSlot = {
  functional: true,
  props: {
    row: Object,
    render: Function,
    index: Number,
    column: {
      type: Object,
      default: null,
    },
  },
  // render 函數
  render: (h, context) => {
    const params = {
      row: context.props.row,
      index: context.props.index,
    };
    if (context.props.columns) params.columns = context.props.columns;
    return context.props.render(h, params);
  },
};
export default {
  name: "TableList",
  components: { exSlot },
  props: {
    data: {
      type: Array,
      default: () => [],
    },
    update: {
      type: Number,
      default: () => null,
    },

    // 是否顯示合計列
    showSummary: {
      type: Object,
      default: () => {
        return {
          show: false,
          sumText: "總計",
        };
      },
    },
    // 需要通過那個欄位屬性進行比較合併
    spanName: {
      type: String,
      default: () => {
        return null;
      },
    },
    // 需要合併數組
    spanColumnArr:{
      type:Array,
      default:()=>{
        return [0]
      }
    },
    tooltipTheme: {
      type: String,
      default: "dark",
    },
    // 是否顯示表頭
    showHeader: {
      type: Boolean,
      default: true,
    },
    // 是否添加排序列
    indexShow: {
      type: Boolean,
      default: true,
    },
    showTable: {
      type: Boolean,
      default: true,
    },
    // 是否顯示選擇框列
    selection: {
      type: Boolean,
      default: false,
    },
    // 欄位名
    columns: {
      type: Array,
      default: () => [],
    },
    // 是否含有邊框
    border: {
      type: Boolean,
      default: false,
    },

    // 是否顯示斑馬條紋
    stripe: {
      type: Boolean,
      default: false,
    },
    // 是否是可以編輯的表格
    isEdit: {
      type: Boolean,
      default: false,
    },
    // 是否固定右側一列,只對右側操作欄起作用
    fixed: {
      type: String,
      default: "right",
    },

    // 是否顯示分頁
    pagination: {
      type: Boolean,
      default: false,
    },
    // 分頁的位置
    paginationPosition: {
      type: String,
      default: "center",
    },
    total: {
      required: false,
      type: Number,
    },
    page: {
      type: Number,
      default: 1, // 預設第一頁
    },
    limit: {
      type: Number,
      default: 10, // 預設每頁20條
    },
    pageSizes: {
      type: Array,
      // default: [10, 20, 30, 50]
      default: function () {
        return [1, 2, 3, 5]; // 預設顯示可選的每頁多少條數據
      },
    },
    layout: {
      type: String,
      default: "total, sizes, prev, pager, next, jumper",
    },
    background: {
      type: Boolean,
      default: true,
    },
    autoScroll: {
      type: Boolean,
      default: true,
    },
    hidden: {
      type: Boolean,
      default: false,
    },
    className: {
      type: String,
      default: "",
    },
    render: {
      type: Function,
      default: function () {},
    },
  },
  data() {
    return {
      cloneColumns: [],
      spanArr: [], // 跨行數組
      pos: null, // 跨行數組
    };
  },
  computed: {
    // 當前頁多少條數據並且賦值給父組件
    currentPage: {
      get() {
        return this.page;
      },
      set(val) {
        this.$emit("update:page", val);
      },
    },
    // 改變當前頁幾條數據得值賦值給父組件
    currentSize: {
      get() {
        return this.limit;
      },
      set(val) {
        this.$emit("update:limit", val);
      },
    },
  },
  created() {
    this.cloneColumns = JSON.parse(JSON.stringify(this.columns));
  },
  watch: {
    columns(value) {},
  },
  mounted() {
    if (this.spanName) {
      this.getSpanArr(this.data);
    }
  },

  methods: {
     // 合同單元格直接傳入:spanName="id或者其他欄位屬性名"
    getSpanArr(data) {
      for (let i = 0; i < data.length; i++) {
        if (i === 0) {
          this.spanArr.push(1);
          this.pos = 0;
        } else {
          // 判斷當前的元素和上一個元素是否相同
          // name 需要通過哪個欄位來進行比較合併
          if (data[i][this.spanName] === data[i - 1][this.spanName]) {
            this.spanArr[this.pos] += 1;
            this.spanArr.push(0);
          } else {
            this.spanArr.push(1);
            this.pos = i;
          }
        }
      }
    },

  // 合併
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (this.spanColumnArr.includes(columnIndex)) {
        const _row = this.spanArr[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return {
          rowspan: _row,
          colspan: _col,
        };
      }
    },

    // 自定義合計行
    summaryMethod(params) {
      const { columns, data } = params;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "總計";
          return;
        }
        const values = data.map((item) => item[column.property]);
        let num = 0;
        for (let i = 0; i < values.length; i++) {
          if (values[i]) {
            num += Number(values[i]);
            sums[index] = num;
          } else {
            if (isNaN(values[i])) {
            } else {
              num += Number(values[i]);
              sums[index] = num;
            }
          }
        }
        if (column.property === "lv1Time" || column.property === "lv2Time") {
          if (values.filter(Boolean).length === 0) {
            sums[index] = "";
          } else {
            let num = 0;
            for (let i = 0; i < values.length; i++) {
              if (values[i]) {
                num += Number(values[i]);
                sums[index] = num;
              } else {
                if (isNaN(values[i])) {
                } else {
                  num += Number(values[i]);
                  sums[index] = num;
                }
              }
            }
          }
        }
      });
      let arr = [];
      sums.map((i, index) => {
        if (index === 0) {
          arr.push(i);
        } else {
          if (!isNaN(i)) {
            arr.push(i);
          } else {
            arr.push("");
          }
        }
      });
      return arr;
    },
    handleFilterChange(filters) {
      if (filters.length > 0) {
        this.$refs.filterTable.clearSelection();
        this.$refs.filterTable.toggleRowSelection(filters.pop());
      } else {
        this.columns.map((item) => {
          // 判斷當前是那一列進行了篩選
          if (item.prop === Object.keys(filters)[0]) {
            item.filterValues = filters;
          }
        });

        this.$emit("filtersParams", this.columns);
      }
    },
    // 當前行當前列數據是否有效,無效的話,返回--占位符
    formatter(row) {
      if (row) {
        return isNaN(parseFloat(row)) && isFinite(row)
          ? '<span class="isNaN">--</span>'
          : row;
      } else {
        return '<span class="isNaN">--</span>';
      }
    },
    /**
     * @param {*}
     * @return {*}
     * @author: Q
     * @Date: 2021-09-01 11:56:37
     * @description: 已選的數據項
     */
    handleSelectionChange(val) {
      this.$emit("selectVal", val);
    },
    handleSizeChange(val) {
      this.pageSize = val;
      this.$emit("pagination", { pageIndex: this.page, pageSize: val });
    },
    handleCurrentChange(val) {
      this.$emit("pagination", { pageIndex: val, pageSize: this.limit });
    },
    // 修改按鈕的點擊事件
    editClick(val) {
      this.$emit("edit", val);
    },
    // 刪除按鈕點擊事件
    deleteClick(val) {
      this.$confirm("此操作將永久刪除該文件, 是否繼續?", "提示", {
        confirmButtonText: "確定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$emit("del", val);
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消刪除",
          });
        });
    },
  },
};
</script>

<style lang="scss">
.table-container {
  text-align: center;
  .el-pagination {
    margin-left: 0 !important;
    margin-top: 0 !important;
    background: #fff !important;
    height: 112px;
    line-height: 112px;
    display: flex;
    justify-content: center;
    align-items: center;
    ul {
      display: flex;
      justify-content: space-around;
      align-items: center;
      li {
        border-radius: 6px !important;
        color: #666666 !important;
      }
      .active {
        color: #fff !important;
        background: #1677ffff !important;
      }
    }
    button {
      border-radius: 6px !important;
      color: #666666 !important;
    }
  }
}
.table-container.el-table {
  margin-top: 20px;
}

.table-container .el-pagination {
  margin-top: 20px;
  margin-left: 20px;
}
.isNaN {
  color: red;
}
</style>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 數據治理是推動大型集團企業轉型升級、提升競爭優勢、實現高質量發展的重要引擎。通過全鏈數據結構化,實現業務對象、業務規則、業務流程數字化,推進全鏈業務深度數字化,夯實數據運營底座。 廈門國貿集團股份有限公司(簡稱“國貿股份”)是國有控股上市公司,同時也是首批全國供應鏈創新與應用示範企業,在“十四五”規 ...
  • 摘要:其實游戲客戶對資料庫的訴求是很明確的,資料庫應當“放心存放心用”。 本文分享自華為雲社區《華為雲GaussDB(for Redis)揭秘第27期:聊聊游戲業務怎麼用高斯Redis》,作者:高斯Redis官方博客。 華為雲資料庫團隊是比較重視技術洞察的,對客戶真實的業務場景也比較看重。年初出差了 ...
  • GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 作者: 花家舍 文章來源:GreatSQL社區原創 前文回顧 實現一個簡單的Database系列 譯註:cstack在github維護了一個簡單的、類似 ...
  • 生活中存在同時使用兩個微信的情況,一個工作一個生活,這時希望同時在電腦上登錄兩個賬號。如何做到呢?步驟如下: 右鍵單擊“微信”圖標,選擇屬性,目標框內的路徑就是微信安裝路徑,複製目標框里的內容。 將如下命令複製到 TXT 文件保存,再將該文件重命名,主要是將尾碼名改成“.bat”文件。 @echo ...
  • 好家伙,本篇為做題思考 書接上文 題目如下: 1.請給出下列代碼的輸出結果,並配合"消息隊列"寫出相關解釋 async function foo() { console.log(2); console.log(await Promise.resolve(8)); console.log(9); } ...
  • 一般來說,項目由子模塊組成,拿到後端提供過來的介面,一般也是按照子模塊來分類提供的.請教一下各位,你們前端項目是如何管理api的? 希望各位貼點你們的優秀代碼段上來學習學習. 常見: 各個模塊的api存放到單獨的js文件里,返回一個請求實例promise對象 使用的時候根據需求引入相應的請求方法 / ...
  • 其他章節請看: webgl 系列 變換矩陣和動畫 動畫就是不停地將某個東西變換(transform)。例如將三角形不停地旋轉就是一個動畫 和 CSS transform 類似,變換有三種形式:平移、縮放和旋轉。 簡單的變換用普通表達式容易實現,如果事情複雜,比如旋轉後平移,這時就可以使用變換矩陣。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 網站效果演示:ashuai.work:8888/#/myLoad GitHub倉庫地址代碼:github.com/shuirongshu… 載入中思路分析 實現載入中效果,一般有兩種方式: 第一種是:搞一個load組件,然後使用Vue.e ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...