vue - element 表格使用總結(分頁器、查詢表單、多級表頭、展開行、自定義列、後端排序、響應式高度)

在這裏插入圖片描述
參加工作工作半年了,平日裏主要使用 element-ui 組件庫,磕磕碰碰也踩了不少坑。今日閒來無事,針對該組件庫中的 el-table 組件的使用做個總結,也方便以後查找。

TIPS:

  1. 本文只列出一些關鍵性的思路和代碼,欲瞭解更多的信息,還是去看官網吧!
  2. 本文純屬個人實踐總結所得,如有不足或錯誤,歡迎指出!

1. 最最基礎的表格

千里之行始於足下。

在基礎表格的基礎上,添加分頁器(分頁功能)、過濾器(過濾數據),查詢表單(列表數據查詢),排序按鈕(前端默認排序)、複選框(可對選擇的一條或者多條數據進行操作)等,就能實現很多的功能。

表格常用屬性說明如下:

參數 說明 類型 默認值 參考值
data 顯示的數據 array ---- 在表格初始化時,獲取表格數據
prop 對應列內容的字段名,也可以使用 property 屬性 string ---- 在表格初始化時,獲取表格數據
label 顯示的標題 string ---- ----
width 對應列的寬度 string ---- ----
min-width 對應列的最小寬度,與 width 的區別是 width 是固定的,min-width 會把剩餘寬度按比例分配給設置了 min-width 的列 string ---- 將表格數據列的最後一列用 min-widtn 來設置最小寬度
border 爲表格添加邊框 boolean false true

這就不列出關鍵代碼了,下面附上一個官網上的效果圖。
在這裏插入圖片描述

2. 帶分頁器的表格(後端分頁)

數據量比較大時,分頁功能就顯得尤爲重要了。

開發系統中所使用的表格,基本都帶有分頁器,實現上使用的是後端分頁。

說明: 爲表格添加分頁功能,首先要在頁面上增加分頁器,其次就是將分頁器的分頁邏輯與表格數據綁定起來。分頁能與其它功能配合使用,比如:查詢功能、重置功能、篩選功能等。

關鍵代碼示例如下所示:

<template>    
  <div class="item-management-container">    
    <div class="item-management-text">    
      <el-table    
        v-loading="loading"    
        :data="tableData"    
        stripe    
        style="width: 100%"    
        :header-cell-style="getHeaderStyle"    
        min-height="380"    
        :row-style="{ 'line-height': 0 }"    
        :cell-style="{ 'padding': '4px' }"    
      >    
        <el-table-column    
          prop="itemCode"    
          label="貨物代碼"    
          width="180"    
          :show-overflow-tooltip="true"    
        />    
        <el-table-column    
          prop="itemName"    
          label="貨物名稱"    
          width="180"    
          :show-overflow-tooltip="true"    
        />    
       <!-- …… -->
    
      </el-table>    
    
      <pagination    
        :total="pagination.total"    
        :page.sync="pagination.listQuery.page"    
        :limit.sync="pagination.listQuery.limit"    
        style="float: right; marginTop: -10px; marginBottom: -20px;"    
        @pagination="getList"    
      />    
    
    </div>    
    <!-- 返回頁面頂部按鈕 -->    
    <back-to-top />    
  </div>    
</template>    
    
<script>    
import Pagination from '@/components/Pagination'    
import BackToTop from '@/components/BackToTop'    
    
export default {    
  name: 'ItemManagement',    
  components: { Pagination, BackToTop },    
  data() {    
    return {    
      loading: false,    
      // 表格數據    
      tableData: [],    
      // 分頁器設置數據    
      pagination: {    
        total: 0,    
        listQuery: {    
          page: 1,    
          limit: 10    
        }    
      },    
      // 表格數據分頁配置(可包括分頁器數據和查詢數據)    
      pageConfig: {    
        pageNum: 1,    
        pageSize: 10    
      },    
    }    
  },    
  created() {    
    // 頁面初始化好以後加載必需的初始數據    
    this.getTableData(this.pageConfig)    
  },    
  methods: {    
    // 設置表格頭部樣式    
    getHeaderStyle({ row, column, rowIndex, columnIndex }) {    
      if (rowIndex === 0) {    
        return {    
          'background-color': '#F6F7FD',    
          'line-height': 3,    
          'padding': 0    
        }    
      }    
    },    
  
    getList(page, limit) {    
      // 當分頁器頁碼或分頁數發生改變時,重新請求表格數據     
      const pageConfig = {}    
      pageConfig.pageNum = Number(page.page)    
      pageConfig.pageSize = Number(page.limit)    
      this.getTableData(pageConfig)    
    }    
	getTableData(pageConfig) {
		// 根據分頁參數,發送 api 請求,獲取表格數據,設置 tableData 和 loading
	}
  }    
}    
</script>    
<style lang='scss' scoped>    
.item-management {    
  &-container {    
    margin: 30px;    
  }    
  &-text {    
    font-size: 30px;    
    line-height: 46px;    
  }    
}    
</style>   

效果圖如下所示:
在這裏插入圖片描述

表格屬性說明如下:

參數 說明 類型 默認值 參考值
v-loading 爲表格添加加載中的效果 boolean false ----
stripe 是否爲斑馬紋 table boolean false ----
header-cell-style 表頭單元格的 style 的回調方法,也可以使用一個固定的 Object 爲所有表頭單元格設置一樣的 Style。 Function({row, column, rowIndex, columnIndex})/Object ---- 可參考關鍵代碼中的getHeaderStyle 函數
row-style 行的 style 的回調方法,也可以使用一個固定的 Object 爲所有行設置一樣的 Style。 Function({row, rowIndex})/Object ---- { ‘line-height’: 0 }
cell-style 單元格的 style 的回調方法,也可以使用一個固定的 Object 爲所有單元格設置一樣的 Style。 Function({row, column, rowIndex, columnIndex})/Object ---- { ‘padding’: ‘4px’ }"
show-overflow-tooltip 當內容過長被隱藏時顯示 tooltip boolean false true

分頁器屬性說明如下:

參數 說明 類型 默認值 參考值
total 總條目數 number ---- 從後臺獲取到數據後,用記錄條數設置
page 當前頁數 支持 .sync 修飾符 number ---- ----
limit 每頁顯示條目個數,支持 .sync 修飾符 number 20 10

分頁器事件說明如下:

事件名稱 說明 回調參數 參考邏輯
pagination 當 limit 或者 page 發生改變時會觸發 { page, limit } 當分頁參數發生變化時,發送的查詢請求不僅要有新的分頁參數,還要始終帶上查詢參數,可參考關鍵代碼中的 getList

3. 帶查詢表單的表格

表格數據較多時,查詢表單可以幫助用戶快速找到需要的數據。

說明: 查詢表單被放置在表格之前,帶有展開/收起按鈕。

查詢操作的相關邏輯如下:

(1)用戶點擊查詢按鈕,前端向後端發送查詢請求(包含用戶輸入關鍵字以及分頁參數);獲取到響應後,解析數據,刷新表格數據;可參考關鍵代碼中的 handleSearch 方法。
(2)用戶點擊重置按鈕,前端清空界面上查詢表單裏的數據,並向後端發送查詢請求(只包含分頁參數以及其它必要的參數,比如倉庫ID),獲得數據後,刷新表格數據;可參考關鍵代碼中的 handleReset 方法。

關鍵代碼示例如下所示:

<template>
  <div class="management-container">
    <div>
      <el-form ref="searchForm" :model="searchForm" :inline="true">
        <el-row>
          <el-col :span="12">
            <el-form-item :label="$t('labelLocationCode')">
              <el-input
                v-model="searchForm.locationCode"
                :placeholder="$t('form.placeholder39')"
                style="width: 27vw;"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="$t('labelLocationType')">
              <el-select
                v-model="searchForm.locationTypeCode"
                filterable
                :placeholder="$t('form.placeholder40')"
                style="width: 27vw;"
              >
                <el-option
                  v-for="item in dictList_LOCATION_TYPE"
                  :key="item.id"
                  :label="item.locationTypeName"
                  :value="item.locationTypeCode"
                />
              </el-select>
              <el-button
                class="expand-btn"
                type="text"
                @click="isCollapsed = !isCollapsed"
              >{{ isCollapsed? $t('btnExpand') : $t('btnCollapse') }}</el-button>
            </el-form-item>
          </el-col>
        </el-row>
        <el-collapse-transition>
          <div v-show="!isCollapsed">
            <el-row>
              <el-col :span="12">
                <el-form-item :label="$t('labelZoneCode')">
                  <el-input
                    v-model="searchForm.zoneCode"
                    :placeholder="$t('form.placeholder37')"
                    style="width: 27vw;"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </div>
        </el-collapse-transition>
        <el-form-item class="btn-group">
          <el-button
            type="primary"
            icon="el-icon-search"
            @click="handleSearch"
          >{{ $t('btnSearch') }}</el-button>
          <el-button type="default" icon="el-icon-refresh" @click="handleReset">{{ $t('btnReset') }}</el-button>
        </el-form-item>
      </el-form>
      <el-table
        ref="table"
        v-loading="loading"
        :data="tableData"
        stripe
        border
        row-key="id"
        style="width: 100%"
        :header-cell-style="getHeaderStyle"
        height="calc(100vh - 310px)"
        :row-style="{ 'line-height': 0 }"
        :cell-style="{ 'padding': 0 }"
      >
        <el-table-column
          prop="locationCode"
          :label="$t('labelLocationCode')"
          width="180"
          :show-overflow-tooltip="true"
        />
        <el-table-column
          prop="locationName"
          v-if="colData[1].istrue"
          :label="$t('labelLocationName')"
          width="150"
          :show-overflow-tooltip="true"
        />
        <!-- .... -->
      </el-table>

      <pagination
        key="location"
        ref="location"
        :total="pagination.total"
        :page.sync="pagination.listQuery.page"
        :limit.sync="pagination.listQuery.limit"
        style="float: right; marginTop: -10px; marginBottom: -20px;"
        @pagination="getList"
      />
    </div>

    <!-- 返回頁面頂部按鈕 -->
    <back-to-top />
  </div>
</template>

<script>
import axios from "axios";
import { mapGetters } from "vuex";
import Pagination from "@/components/Pagination";
import BackToTop from "@/components/BackToTop";
import { Message, MessageBox } from "element-ui";
import {
  getLocations,
} from "@/api/base-data/location";

// 本地國際化數據
import local from "./locals/location";
const viewName = "location";

export default {
  name: "LocationManagement",
  components: { Pagination, BackToTop, UploadExcel },
  data() {
    return {
      loading: false,
      // 控制查詢表單的展開或收起
      isCollapsed: true,
      // 查詢表單
      searchForm: {
        locationCode: null,
        locationTypeCode: null
        // isFrozen: null
      },
      // 表格數據
      tableData: [],
      // 分頁器設置數據
      pagination: { ...this.$global.pagination },
      // 表格數據分頁配置(可包括分頁器數據和查詢數據)
      pageConfig: {
        pageNum: 1,
        pageSize: 10,
        whseId: getWarehouseId()
      },
      // 默認顯示記錄條數
      defaultPageSize: Number(localStorage.getItem("pageSize")) || 10,
      
    };
  },
  computed: {
    ...mapGetters(["device"]),
    searchData: function() {
      const { ...form } = this.searchForm;
      if (!form.locationCode || !form.locationCode.trim()) {
        form.locationCode = null;
      }
      if (!form.zoneCode || !form.zoneCode.trim()) {
        form.zoneCode = null;
      }
      return form;
    }
  },

  created() {
    if (!this.$i18n.getLocaleMessage("zh")[viewName]) {
      this.$i18n.mergeLocaleMessage("zh", local.zh);
      this.$i18n.mergeLocaleMessage("en", local.en);
    }
    
    this.pagination.listQuery.limit = this.defaultPageSize;
    this.pageConfig.pageSize = this.defaultPageSize;

    const pageConfig = {
      ...this.pageConfig,
      ...this.searchData
    };

    this.getTableData(pageConfig);
  },

  methods: {
    // 設置表格頭部樣式
    getHeaderStyle({ row, column, rowIndex, columnIndex }) {
      if (rowIndex === 0) {
        return {
          "background-color": "#F6F7FD",
          "line-height": 3,
          padding: 0
        };
      }
    },
    handleSearch() {
      const pageConfig = {
        ...this.pageConfig,
        ...this.searchData
      };
      this.$nextTick(() => {
        this.$refs.location.resetPagination()
      });
      this.getTableData(pageConfig);
    },
    handleReset() {
      this.searchForm = {};
      this.handleSearch();
    },
    getTableData(listConfig) {
      this.loading = true;
      getLocations(listConfig)
        .then(res => {
          this.tableData = res.result.records;
          // console.log(this.tableData)
          // 設置分頁器
          this.pagination.total = res.result.total;
          this.loading = false;
        })
        .catch(err => {
          console.log("error: ", err);
          this.loading = false;
        });
    },
    getList(page, limit) {
      // 當分頁器頁碼或分頁數發生改變時,重新請求表格數據
      const pageConfig = { ...this.searchData };
      pageConfig.pageNum = Number(page.page);
      pageConfig.pageSize = Number(page.limit);
      this.getTableData(pageConfig);
    }
  }
};
</script>
<style lang='scss' scoped>
.management {
  &-container {
    margin: 30px;
  }
  &-text {
    font-size: 30px;
    line-height: 46px;
  }
}
.btn-group {
  float: right;
  margin-right: 0;
  // clear: both;
}
</style>

效果圖如下所示:
在這裏插入圖片描述

4. 多級表頭表格

數據結構比較複雜的時候,可使用多級表頭來展現數據的層次關係。

說明: 多級表頭的實現,只需要用 el-table-column 標籤嵌套其它的 el-table-column 標籤。

關鍵代碼示例如下所示:

<template>  
  <div class="inventory-management-container">
    <div class="inventory-management-text¬¬¬">
      <el-table  
        v-loading="loading" 
        :data="tableData"
        ref="table"  
        stripe  
        :border="false"  
        style="width: 100%;"  
        :header-cell-style="{'padding': 0, 'textAlign': 'center', }"  
        min-height="380"  
        :row-style="{ 'line-height': 0 }"  
        :cell-style="{ 'padding': .2, 'textAlign': 'center' }"  
        @filter-change="handleFilter"  
      >  
        <el-table-column  
          prop="itemCode"  
          label="貨物代碼"  
          width="180"  
         :show-overflow-tooltip="true"  
       />  
        <el-table-column  
          prop="storageNo"  
          label="單據號"  
          width="180"  
          :show-overflow-tooltip="true"  
        />  
            <el-table-column label="交易前" :cell-style="{ 'padding': '-20px' }">  
        		<el-table-column  
                   prop="originSerialNo"  
                   label="料箱號"  
                   width="180"  
     :show-overflow-tooltip="true"  
               />  
               <el-table-column  
                   prop="originQty"  
                   label="數量"  
                   width="100"  
     :show-overflow-tooltip="true"  
               />  
               <el-table-column  
                   prop="originLocationCode"  
                   label="庫位"  
                   width="150"  
     :show-overflow-tooltip="true"  
               />  
               <el-table-column  
                   prop="originStatus"  
                   label="庫存狀態"  
                   width="100"  
     :show-overflow-tooltip="true"  
               >  
                   <template slot-scope="scope">  
                       {{ scope.row.originStatus | formatInventoryStatus }}  
                   </template>  
               </el-table-column>  
           </el-table-column>  
        <el-table-column label="交易後" :cell-style="{ 'padding': '-20px' }">  
          <!-- .... -->
        </el-table-column>  
                  
        <el-table-column  
            prop="createUser"  
            label="操作人員"  
            width="150"  
  :show-overflow-tooltip="true"  
        />  
        <el-table-column  
            prop="createTime"  
            label="操作時間"  
            width="180"  
  :show-overflow-tooltip="true"  
        >  
            <template slot-scope="scope">  
                {{ scope.row.createTime | formatDateTime }}  
            </template>  
        </el-table-column>  
      </el-table>  
 
    </div>  
    <!-- 返回頁面頂部按鈕 -->  
    <back-to-top />  
  </div>  
</template>  
  
<script>  
import Pagination from '@/components/Pagination'  
import BackToTop from '@/components/BackToTop' 
  
export default {  
  name: 'InventoryTradingQuery',  
  components: { Pagination, BackToTop },  
  data() {  
    return {  
      loading: false,
      // 表格數據  
      tableData: [],  
      // 分頁器設置數據  
      pagination: {  
        total: 0,  
        listQuery: {  
          page: 1,  
          limit: 10  
        }  
      },  
      // 表格數據分頁配置(可包括分頁器數據和查詢數據)  
      pageConfig: {  
        pageNum: 1,  
        pageSize: 10,  
        whseId: getWarehouseId()  
      }
    }  
  },
  created() {
    // 頁面初始化好以後加載必需的初始數據  
     const pageConfig = {  
      ...this.pageConfig  
    }  
    this.getTableData(pageConfig)  
 
  },  
  methods: {  
    // 設置表格頭部樣式  
    getHeaderStyle({ row, column, rowIndex, columnIndex }) {  
      if (rowIndex === 0) {  
        return {  
          'background-color': '#F6F7FD',  
          'line-height': 1,  
                    'padding': '-10px',  
          'text-align': 'center'  
        }  
      }  
    }
  }  
}  
</script>  
<style lang='scss'>  
.inventory-management {  
  &-container {  
    margin: 30px;  
  }  
  &-text {  
    font-size: 30px;  
    line-height: 46px;  
    .form-item {  
      float: left;  
      margin-right: 90px;  
    }	
}  
</style>  

效果圖如下所示:
在這裏插入圖片描述

5. 帶展開行的表格

當信息帶有明顯的主次之分時,可使用帶有展開行的表格來呈現數據。

說明: 通過設置 type=“expand” 和 Scoped slot 可以開啓展開行功能,el-table-column 的模板會被渲染成爲展開行的內容,展開行可訪問的屬性與使用自定義列模板時的 Scoped slot 相同。

關鍵代碼示例如下所示:

<template>  
  <div class="management-container">  
    <div class="management-text"> 
      <el-table 
        v-loading="loading"  
        :data="tableData"  
        ref="table"  
        stripe  
        style="width: 100%"  
        :header-cell-style="getHeaderStyle"  
        min-height="380"  
        :row-style="{ 'line-height': 0 }"  
        :cell-style="{ 'padding': .1 }"  
      >  
        <el-table-column type="expand" fixed="left">  
          <template scope="scope">  
            <el-table  
              v-loading="loading"  
              :data="scope.row.detailsList"  
              style="width: 100%"  
              :header-cell-style="getHeaderStyle"  
              min-height="380"  
              :row-style="{ 'line-height': 0 }"  
              :cell-style="{ 'padding': .1 }"  
            >  
              <el-table-column  
                prop="itemCode"  
                label="貨物代碼"  
                width="180"  
                :show-overflow-tooltip="true"  
              />  
              <el-table-column  
                prop="itemName"  
                label="貨物名稱"  
                width="200"  
                :show-overflow-tooltip="true"  
              />  
              <el-table-column  
                prop="productionBatch"  
                label="生產批次"  
                width="120"  
                :show-overflow-tooltip="true"  
              />  
              <el-table-column  
                prop="qty"  
                label="數量"  
                min-width="100"  
                :show-overflow-tooltip="true"  
              />  
            </el-table>  
          </template>  
        </el-table-column>   
        <el-table-column  
          prop="createUser"  
          label="入庫員"  
          width="120"  
          :show-overflow-tooltip="true"  
        />  
        <el-table-column  
          prop="createTime"  
          label="入庫時間"  
          width="200"  
          :show-overflow-tooltip="true"  
        >  
          <template slot-scope="scope">  
            {{ scope.row.createTime | formatDateTime }}  
          </template>  
        </el-table-column>  
      </el-table>  
  
    </div>  
    <!-- 返回頁面頂部按鈕 -->  
    <back-to-top />  
  </div>  
</template>  
  
<script> 
import Pagination from '@/components/Pagination'  
import BackToTop from '@/components/BackToTop'  
import { Message } from 'element-ui'  
import { getInActs } from '@/api/in-acts/in-acts'  
export default {  
  name: 'InActsQuery',  
  components: { Pagination, BackToTop },  
  data() {  
    return {  
      loading: false,
       tableData: []
      }
    }  
  }, 
  created() {  
    // 頁面初始化好以後加載必需的初始數據  
    const pageConfig = {  
      ...this.pageConfig  
    }  
    this.getTableData(pageConfig)  

  },  
  methods: {  
    // 設置表格頭部樣式  
    getHeaderStyle({ row, column, rowIndex, columnIndex }) {  
      if (rowIndex === 0) {  
        return {  
          'background-color': '#F6F7FD',  
          'line-height': 3,  
          'padding': 0  
        }  
      }  
    }
  
    getTableData(listConfig) {  
      this.loading = true  
      getInActs(listConfig).then(res => {  
        this.tableData = res.result.records  
        // 設置分頁器  
        this.pagination.total = res.result.total  
        this.loading = false  
      }).catch(err => {  
        console.log('error: ', err)  
        this.loading = false  
      })  
    }
  }  
}  
</script>  
<style lang='scss' scoped>  
.management {  
  &-container {  
    margin: 30px;  
  }  
  &-text {  
    font-size: 30px;  
    line-height: 46px;  
  }  
}  
</style>  

效果圖如下所示:
在這裏插入圖片描述

表格屬性說明如下:

參數 說明 類型 默認值 參考值
type 對應列的類型。如果設置了 selection 則顯示多選框;如果設置了 index 則顯示該行的索引(從 1 開始計算);如果設置了 expand 則顯示爲一個可展開的按鈕 string ---- 可選值有:selection/index/expand。可展開的行:type=”expand”;帶多選框的行:type=”selection”

6. 自定義顯示/隱藏列的表格

頁面呈現的數據列可能比較多,而在實際使用時,用戶可能只關注其中的幾列數據,其它的一些數據就顯得無關緊要了。這時候,這些無關數據,就是視覺噪點,應當被儘量“去除”。

說明: 本功能的交互流程爲:用戶在表格表頭任意區域右鍵,在點擊位置出現菜單顯示選擇複選框列表。用戶取消某項的選擇,意味着對應列的數據將會被隱藏。同時,對該表格做的最後的修改,數據將會保存在瀏覽器本地,下次進入該頁面,仍然會使用上次的設置(前提是:用戶沒有清空本地緩存)。

關鍵代碼示例如下所示:

<template>  
  <div class="management-container">  
    <div class="management-text">  
      <el-form ref="searchForm" :model="searchForm">  
 			<!-- …… -->
      </el-form>  
      <el-table  
        ref="table"  
        v-loading="loading"  
        :data="tableData"  
        stripe  
        border  
        style="width: 100%"  
        :header-cell-style="getHeaderStyle"  
        :height="tableHeight"  
        :row-style="{ 'line-height': 0 }"  
        :cell-style="{ 'padding': .1 }"  
        @header-contextmenu="contextmenu"   
      >  
	 <el-table-column  
      prop="storageNo"  
      v-if="colData[0].istrue"  
      label="入庫單號"  
      width="280"  
1.	      :show-overflow-tooltip="true"  
2.	   />  

        <!-- …… -->
      </el-table>  
  
    <!-- colOptions:右擊菜單內容 -->  
    <div v-show="menuVisible" :style="{top:top+ "px",left:left+ "px"}" class="select-menu">  
      <p>定義顯示的表格列</p>  
      <el-checkbox-group v-model="colOptions">  
        <el-checkbox v-for="item in colSelect" :key="item" :label="item" class="custom-checkbox" />  
      </el-checkbox-group>  
    </div>  
  </div>  
</template>  
  
<script>  
import { stringifyObjArr, parseObjArr, stringifyArr, parseArr } from '@/utils/localStorage-json'  
  
export default {  
  name: 'InActsQuery',  
  components: { Pagination, BackToTop },  
  data() {  
    return {  
       // 實現動態表格列數據  
      // colOptions,colSelect中內容的順序必須與表格中表頭的內容順序保持一致  
      colOptions: parseArr('colOptions_inActs')? parseArr('colOptions_inActs') : ['入庫單號', '入庫批次', '料箱號', '貨主代碼', '貨主名稱', '廠商代碼', '廠商名稱', '狀態', '入庫類型', '入庫員', '入庫時間'],  
      colSelect: ['入庫單號', '入庫批次', '料箱號', '貨主代碼', '貨主名稱', '廠商代碼', '廠商名稱', '狀態', '入庫類型', '入庫員', '入庫時間'],  
      colData: parseObjArr('colData_inActs')? parseObjArr('colData_inActs') : [ 
        { title: '入庫單號', istrue: true },  
        { title: '入庫批次', istrue: true },  
        { title: '料箱號', istrue: true },  
        { title: '貨主代碼', istrue: true },  
        { title: '貨主名稱', istrue: true },  
        { title: '廠商代碼', istrue: true },  
        { title: '廠商名稱', istrue: true },  
        { title: '狀態', istrue: true },  
        { title: '入庫類型', istrue: true },  
        { title: '入庫員', istrue: true },  
        { title: '入庫時間', istrue: true }  
      ],  
      menuVisible: false,  
      top: 0,  
      left: 0
    }  
  },  

  watch: {  
    // 動態計算要顯示的數據列  
    colOptions(valArr) {  
      var arr = this.colSelect.filter(i => valArr.indexOf(i) < 0) // 未選中  
      this.colData.filter(i => {  
        if (arr.indexOf(i.title) !== -1) {  
          i.istrue = false  
        } else {  
          i.istrue = true  
        }  
      })  
      // 本地保存數據列顯示與否的設置數據  
      stringifyObjArr('colData_inActs', this.colData)  
      stringifyArr('colOptions_inActs', valArr)  
    },  
  },  
  
  beforeUpdate() {
    // 重新佈局表格
    this.$nextTick(() => {
      this.$refs.table.doLayout();
    });
  },
  
  methods: {  
    // 控制表格列數據的動態顯示  
    contextmenu(row, event) {  
      this.menuVisible = false // 先把右鍵菜單關死,解決用戶在連續分別2個地方右鍵打// 開2個菜單的清空  
      this.menuVisible = true // 顯示自定義菜單  
      window.event.returnValue = false  // 取消瀏覽器右擊默認事件  
      document.addEventListener('click', this.closeMenu)  
      // 獲取鼠標點座標,設置右擊菜單位置  
      this.top = event.clientY  
      this.left = event.clientX  
    },  
    closeMenu() {  
      this.menuVisible = false // 關閉右鍵菜單  
      document.removeEventListener('click', this.closeMenu) // 取消監聽事件  
    } 
  }  
}  
</script>  
<style lang='scss' scoped>  

</style>  

效果圖如下所示:
在這裏插入圖片描述

表格屬性說明如下:

參數 說明 類型 默認值 參考值
header-contextmenu 當某一列的表頭被鼠標右鍵點擊時觸發該事件 Function(column, event) ---- 如上關鍵代碼所示

7. 帶後端排序的表格

表格排序,有前端排序和後端排序兩種。而帶有分頁功能的表格,前端排序就不大適用了。因此,本系統採用了後端排序(這種方式需要後端接口配合)。

說明: 後端排序很簡單,基本原理就是將用戶設置的排序參數作爲查詢參數的一部分,查詢得到表格數據。

關鍵代碼示例如下所示:

<template>  
  <div class="management-container">  
    <div class="management-text">  
      <el-form ref="searchForm" :model="searchForm">  
        <!--  ……  -->
      </el-form>  
      <el-table  
        ref="table"  
        v-loading="loading"  
        :data="tableData"  
        stripe  
        border  
        style="width: 100%"  
        :header-cell-style="getHeaderStyle"  
        :height="tableHeight"  
        :row-style="{ 'line-height': 0 }"  
        :cell-style="{ 'padding': .1 }"  
        @sort-change="handleSortChange"  
      >  
        <!--  ……  -->
        <el-table-column  
          prop="createTime"  
          label="入庫時間"  
          min-width="200"  
          sortable="custom"  
        >  
          <template slot-scope="scope">  
            {{ scope.row.createTime | formatDateTime }}  
          </template>  
        </el-table-column>  
      </el-table>  
    </div>  
  </div>  
</template>  
  
<script>    
export default {  
  name: 'InActsQuery',  
  components: { Pagination, BackToTop },  
  data() {  
    return {  
      // 查詢表單  
      searchForm: {  
        storageNo: null,  
         // ……
         // 自定義排序字段  
        orderItems: []  
      },  
      // 表格數據  
      tableData: []
    }  
  },    
  methods: {  
    handleReset() {  
      this.searchForm = { dateRange: null },  
      this.filterData = {}  
      // 重置自定義排序條件  
      this.searchForm.orderItems = []  
      this.$refs['table'].clearSort()  
      // 重置查詢表單時,連着分頁器一起重置  
      // 重置表格篩選條件  
      this.$refs['table'].clearFilter()  
      this.handleSearch()  
    },  
  
      // 自定義排序  
    handleSortChange({column, prop, order}) {  
      let asc = order === 'ascending'? true : false  
      for (let i = 0; i < this.searchForm.orderItems.length; i++) {  
        const element = this.searchForm.orderItems[i]  
        if(element.column === prop) {  
          element.asc = asc  
          return  
        }  
      }  
      let item = {  
        asc: asc,  
        column: prop  
      }  
      this.searchForm.orderItems.push(item)  
    }  
  }  
}  
</script>  
<style lang='scss' scoped>  
</style>  

效果圖如下所示:
在這裏插入圖片描述

表格屬性說明如下:

參數 說明 類型 默認值 參考值
sort-change 當表格的排序條件發生變化的時候會觸發該事件 Function(column, prop, order) ---- 如上關鍵代碼所示
sortable 對應列是否可以排序,如果設置爲 ‘custom’,則代表用戶希望遠程排序,需要監聽 Table 的 sort-change 事件 boolean, string(true, false, ‘custom’) false ‘custom’

8. 響應式表格高度的表格

表格高度如果不限制的話,整個表格就是“展開”的狀態。如果表格數據列很多,出現了橫向的滾動條,用戶想要操作最後一行的最後一列,操作就會顯得比較繁瑣。這時候,如果橫向滾動條始終是顯示在頁面上的,這將大大簡化用戶的操作。

說明: 設置表格的高度本身是一件很容易的事。但,想要響應式的設置表格高度,就複雜一些了。其關鍵之處,就是要響應式地根據瀏覽器窗口尺寸的變化,動態計算設置表格高度。
表格高度 = 瀏覽器窗口高度 – 表格距離窗口頂部的距離 – 表格下方要預留的高度

關鍵代碼示例如下所示:

<template>  
  <div class="management-container">  
    <div class="management-text">  
      <el-form ref="searchForm" :model="searchForm">  
         <!--  ……  -->
      </el-form>  
      <el-table  
        ref="table"  
        v-loading="loading"  
        :data="tableData"  
        stripe  
        border  
        style="width: 100%"  
        :header-cell-style="getHeaderStyle"  
        :height="tableHeight"  
        :row-style="{ 'line-height': 0 }"  
        :cell-style="{ 'padding': .1 }"  
      >  
        <!--  ……  -->
      </el-table>  
  
      <pagination  
        :total="pagination.total"  
        :page.sync="pagination.listQuery.page"  
        :limit.sync="pagination.listQuery.limit"  
        style="float: right; marginTop: -10px; marginBottom: -20px;"  
        @pagination="getList"  
      />  
    </div>  
  </div>  
</template>  
  
<script>    
export default {  
  name: 'InActsQuery',  
  components: { Pagination, BackToTop },  
  data() {  
    return {  
       // 表格初始化高度
       // 250  -> 表格距離瀏覽器頂端的距離
       // 90   -> 表格下方的分頁器的高度
       // 這兩個數據,需視具體情況進行調整,但計算公式是一樣的  
      tableHeight: (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - 90 - 250  
    }  
  },  
  
  watch: {  
    // 每次表格高度變化以後,等400ms,再進行高度的設置,這是爲了減少表格的頻繁的// 重繪重排
    tableHeight(val) {  
      if(!this.timer) {  
        this.tableHeight = val  
        this.timer = true  
        setTimeout(() => {  
          this.timer = false  
        }, 400)  
      }  
    }  
  },  
  
  mounted() {  
    window.onresize = () => {  
      return (() => {  
        windowwindow.tableHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight  
        this.tableHeight = window.tableHeight - this.$refs.table.$el.offsetTop - 90  
      })()  
    }  
  }
}  
</script>  
<style lang='scss' scoped>  
</style>  

效果圖如下所示:
在這裏插入圖片描述

表格屬性說明如下:

參數 說明 類型 默認值 參考值
height Table 的高度,默認爲自動高度。如果 height 爲 number 類型,單位 px;如果 height 爲 string 類型,則這個高度會設置爲 Table 的 style.height 的值,Table 的高度會受控於外部樣式。 string/number ---- 如上關鍵代碼所示

最簡單的一種方式:

// table 高度設置:使用動態高度 100vh
height="calc(100vh - 310px)"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章