主頁 > 企業開發 > 基于element-ui進行二次封裝的表格組件

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

2023-03-10 08:41:50 企業開發

<!--
* @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 >--</span>'
          : row;
      } else {
        return '<span >--</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>

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/546361.html

標籤:其他

上一篇:創建型-原型模式

下一篇:記錄--Vue自定義指令實作加載中效果v-load(不使用Vue.extend)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more