一、分析需求
- 這裏先上一張圖說明
需求
:
根據後端返回的數據 (res
是一個數組,它的元素是一個對象,對象裏面的ext
屬性是一個對象,它又包含了,default
、free
和pay
三個屬性,且這三個都是數組格式。):
- 渲染出一個這樣子的
表格
:
res
數據:
res
的每一個元素的直接屬性name
(即爲郵費模板名稱,比如成都運費模板),res
的ext
屬性下的三個數組default
、free
、pay
,每一個數組要大的一行(這一行中,第一列是運送到的地址的名字,這裏定義的是area
屬性,但後端是未給到這個字段的,可自己處理數據添加該字段 ,這裏就不細說了。) 這個area
屬性佔據的這一列,在頁面的展示效果 應該是多行合併的效果。
二、代碼實現:
<template>
<div class="layout">
<el-table :data="res" >
<el-table-column prop="name">
<template slot-scope="scope">
<div class="tab_header">
<span style="font-weight:600;">{{scope.row.name}}</span>
<div class="operate">
<span @click="handleEdit(scope.$index, scope.row)">修改</span>
<span @click="handleDelete(scope.$index, scope.row)">刪除</span>
</div>
</div>
<!-- 這裏要實現 多個表格共用一個表頭,故需做判斷,當表格要渲染的數據爲default這個數組的時候,才顯示錶頭的label值 -->
<!-- 注意:當label無值的時候,還是會佔用空間,故當前表格在頁面上會出現一個代表表頭的空行,需要手動更改(重寫)Element表格的 thead樣式 -->
<div v-for="item in (scope.row.ext)" :key="item.id">
<el-table :data="item" border :class="item!==scope.row.ext.default?'tab-thead-style':''" style="box-sizing: border-box;border-top:none;" :span-method="objectSpanMethod">
<el-table-column :label="item===scope.row.ext.default?'運送到':''" prop="area"></el-table-column>
<el-table-column :label="item===scope.row.ext.default?'首重':''" prop="weight"></el-table-column>
<el-table-column :label="item===scope.row.ext.default?'運費':''" prop="first_price"></el-table-column>
<el-table-column :label="item===scope.row.ext.default?'續重':''" prop="weight_incre"></el-table-column>
<el-table-column :label="item===scope.row.ext.default?'最終運費':''" prop="extend_price"></el-table-column>
</el-table>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data () {
return {
// res 參考的是後端返回的數據格式,
res: [
{
id: 1,
dealer_id: 0,
name: '成都運費模板',
type: 1,
ext: {
default: [{ area: '默認', type: 1, region: '1', weight: '首重d', weight_incre: '續重d', first_price: '運費d', extend_price: '最終運費d' }],
free: [{ area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '續重f', first_price: '運費f', extend_price: '最終運費f' }, { area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '續重f', first_price: '運費f', extend_price: '最終運費f' }],
pay: [{ area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }]
}
},
{
id: 2,
dealer_id: 0,
name: '重慶運費模板',
type: 2,
ext: {
default: [{ area: '默認1', type: 1, region: '1', weight: '首重d', weight_incre: '續重d', first_price: '運費d', extend_price: '最終運費d' }],
free: [{ area: 'free1', type: 1, region: '1', weight: '首重f', weight_incre: '續重f', first_price: '運費f', extend_price: '最終運費f' }, { area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '續重f', first_price: '運費f', extend_price: '最終運費f' }],
pay: [{ area: 'pay1', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay1', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '續重p', first_price: '運費p', extend_price: '最終運費p' }]
}
}
]
}
},
methods: {
handleEdit (index, row) {
console.log(index, row)
},
handleDelete (index, row) {
console.log(index, row)
},
objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
if (rowIndex === 0) {
let maxLen
this.res.forEach(val => {
const arr = [val.ext.default.length, val.ext.free.length, val.ext.pay.length]
arr.sort((a, b) => a - b)// arr數組 按數字大小從小到大排序
maxLen = arr.pop()// 取出排序後的數組arr中的最後一個元素
})
return {
// 這個rowspan應該據 ext的default,pay,free的長度不同來定,取最大長度
rowspan: maxLen,
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
}
}
}
</script>
<style lang="scss">
.layout{
.tab_header{
color:#333;
padding:0 5px 0 5px;
height:45px;
line-height:45px;
border:1px solid #eee;display:flex;
justify-content: space-between;
background:rgb(233, 225, 225);
}
.operate{
span{
font-size: 14px;
margin-right: 20px;
margin-right:20px;
color:#409EFF;
cursor: pointer;
}
}
/* 處理多個表格共用一個表頭時,表頭處出現多餘空行的問題 (label置空後還是佔據空間問題) */
.tab-thead-style{
thead{
display: none;
}
}
}
</style>
三、知識點總結:
-
爲什麼要採用這種方式解決(渲染)?
① . 項目用的UI組件是
Element
,它的Table表格組件,沒有直接處理行的操作。② .
el-table
,它是通過注入data
對象數組,並在el-table-column
中用prop
屬性來對應對象中的鍵名來填入數據,從而渲染出渲染表格。其中el-table-column
表示一個列,label
屬性來定義表格的列名,即對象的一個鍵名代表一列;③ . 沒想到更優的解決辦法,O(∩_∩)O哈哈~
-
多個表格共用一個表頭時,注意:
①. 需做判斷,同時注意
label
的值。②. 當
el-table-column
的屬性label
無值的時候,還是會佔用空間,故當前表格在頁面上會出現一個代表表頭的空行,需要手動更改(重寫)Element
表格的thead
樣式 -
table表格嵌套的時候,注意:
① .
Element
的Table
組件可 自定義列模板,主要是利用它實現表格嵌套部分,通過Scoped slot
可以獲取到row, column, $index
和store
(table 內部的狀態管理)的數據,更多用法參考官網。②.
Element
的Table
組件可 合併行或列 ,多行或多列共用一個數據時,可以合併行或列;通過給table
傳入span-method
方法可以實現合併行或列,參考上述代碼的 **objectSpanMethod
**方法(該表格的第一列需要合併多行——合併渲染表格的data
數組的長度那麼多行) 或者官網。