基於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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...