參加工作工作半年了,平日裏主要使用 element-ui 組件庫,磕磕碰碰也踩了不少坑。今日閒來無事,針對該組件庫中的 el-table 組件的使用做個總結,也方便以後查找。
TIPS:
- 本文只列出一些關鍵性的思路和代碼,欲瞭解更多的信息,還是去看官網吧!
- 本文純屬個人實踐總結所得,如有不足或錯誤,歡迎指出!
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)"