一、固定数据和已知合并行列数的合并
以下分别设置了合并一行和合并多个一行的的表格合并方法
<template>
<div>
<el-table :data="tableData" :cell-style="cellStyle" :header-cell-style="{ color: 'red', borderColor: 'red' }"
:span-method="arrySpanMore" border style="width: 100%">
<el-table-column prop="id" label="ID" width="180" align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center">
</el-table-column>
<el-table-column prop="amount1" label="数值 1" align="center">
</el-table-column>
<el-table-column prop="amount2" label="数值 2" align="center">
</el-table-column>
<el-table-column prop="amount3" label="数值 3" align="center">
</el-table-column>
<el-table-column prop="amount4" label="数值 4" align="center">
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [{
id: '12987122',
name: '王小虎',
amount1: '11',
amount2: '20',
amount3: 12,
amount4: 100
}, {
id: '12987123',
name: '王小虎',
amount1: '11',
amount2: '20',
amount3: 12,
amount4: 100
}, {
id: '12987124',
name: '王小虎',
amount1: '11',
amount2: '20',
amount3: 12,
amount4: 100
}, {
id: '12987125',
name: '王小虎',
amount1: '11',
amount2: '20',
amount3: 12,
amount4: 100
}, {
id: '12987126',
name: '王小虎',
amount1: '539',
amount2: '20',
amount3: 12,
amount4: 100
}]
}
},
created() {},
methods: {
/**
* row:表格行
* column:表格列
* rowIndex:表格行下标
* columnIndex:表格列下标
* */
// 设置表格合并单元格的方法(合并单行的方法)
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
// 从表格第二行(下标为1),和第四行(下标为3)开始合并
if (rowIndex === 1||rowIndex === 3) {
// 从表格第二列(下标为1)开始合并
if (columnIndex === 1) {
// 返回行和列的合并数量,可返回数组[1,3]或者对象:如下,rowspan代表有1行要合并,colspan代表有三列要合并
return {
rowspan: 1,
colspan: 3
}
} else if (columnIndex===2||columnIndex===3){
// 代表合并第三列和第四列的值完全省略,合并了几列,就要省略几列的值,
// 这个判断必须要加,不然第五列的值就不是填第五列的值了,而是填的第三列的值,第六列填的是第四列的值
return [0,0]
}
}
},
// 合并多行单元格的方法
arrySpanMore({row, column, rowIndex, columnIndex}) {
// 从第一行开始合并
if (rowIndex===0) {
// 从第二列开始合并
if (columnIndex === 1) {
return {
// 合并数量为两行,三列
rowspan: 2,
colspan: 3
}
} else if (columnIndex===2||columnIndex===3) {
// 忽略第一行的三、四列的数据
return [0,0]
}
} else if (rowIndex===1&&(columnIndex===1||columnIndex===2||columnIndex===3)) {
// 忽略第二行的第二、三、四;列的数据
return [0,0]
}
},
// 设置表格内边框和字体颜色(样式)
cellStyle({ row, column, rowIndex, columnIndex }) {
return "border-color:black!important;font-size:20px!important; color:red!important;"
}
}
}
</script>
<style>
/* 设置上边框的颜色 */
.el-table td, .el-table th.is-leaf,.el-table--border, .el-table--group{
border-color: green;
}
/* 设置下边框颜色 */
.el-table--border::after, .el-table--group::after, .el-table::before{
background-color: blue;
}
</style>
**
合并一行:
合并多行:
二、后台请求数据菜单树形结构的合并
一般后台请求回来的菜单数据,展示成一级菜单和二级菜单的所属关系表格,需要对数据做特殊处理,表格效果如下:
代码:
主要的处理逻辑:
1.需要把数据处理成合适的数组,如同属于相同一级菜单的数据要放在一起,才能合并到一块,数据要是树形结构的形式才能用v-for循环出来多个操作权限数据
2.表格合并方法主要是代码中的arraySpanMethod,处理表格的合并相的方法为代码中的merage
<template>
<div class="centralizemgt">
<section class="app-container">
<!-- 列表顶部工具 -->
<div class="topbox">
<div>
<el-button type="primary" @click="back_Btn" size="mini" class="backbtn">返回</el-button>
</div>
<div>
<el-button type="primary" size="mini" @click="savePower">保存授权</el-button>
<el-button type="primary" size="mini" @click="AllSelect">操作权限全选</el-button>
<el-button type="primary" size="mini" @click="cancelAllSelect">取消操作权限全选</el-button>
</div>
</div>
<!-- 列表 -->
<el-table :data="allMenus" ref="multipleTable" class="commomLoading" @row-click="handleCurrentChange" border highlight-current-row @selection-change="selsChange" :span-method="arraySpanMethod" style="width: 100%;margin-top:10px">
<el-table-column type="selection" width="55" align="center">
</el-table-column>
<el-table-column type="index" width="60" align="center">
</el-table-column>
<el-table-column prop="parentname" label="一级菜单" min-width="80" align="center">
</el-table-column>
<el-table-column prop="name" label="二级菜单" min-width="80" align="center">
</el-table-column>
<el-table-column label="操作权限" min-width="200" align="center">
<template slot-scope="scope">
<el-checkbox-group v-model="scope.row.checked">
<el-checkbox v-for="(item, index) in scope.row.handle" :label="item.Code" :key="index">{{item.Name}}</el-checkbox>
</el-checkbox-group>
</template>
</el-table-column>
</el-table>
</section>
</div>
</template>
<script>
import Qs from 'qs'
import {
getAllMenuInfo,
getAllHandleInfo,
giveRoles,
giveHandle,
getGiveRolesInfoList,
lookPowerGis
} from './apis/index.js'
export default {
data() {
return {
id: null, // 角色ID
menuData: [], // 所有树形菜单,包括一级
allMenus: [], // 所有菜单(二级菜单)
handles: [], // 所有操作权限
checkedHandle: [], // 选中的操作权限
menu1Arr: [], // 一级菜单要合并数组 [2,0,1,3,0,0] 代表第一二行合并,第三行不变,第四五六行合并,0代表原本的那一行被合并,因此这个列被消除
menu1Pos: 0, // 一级菜单要合并数组内容的序号
sels: [] // 选中项
}
},
created() {
this.id = this.$route.params.id
// 获取所有操作权限
this.getAllHandle()
},
mounted() {
},
methods: {
/** 加载初始数据部分 */
// 点击当前行
handleCurrentChange(row, event, column) {
this.$refs.multipleTable.toggleRowSelection(row, true) // 点击选中
},
// 返回
back_Btn() {
this.$router.back()
},
// 获取全部操作权限信息
getAllHandle() {
getAllHandleInfo().then(res => {
this.handles = res.data
// 获取所有菜单权限
this.getAllMenu()
})
},
// 获取全部菜单信息
getAllMenu() {
// 获取菜单信息
getAllMenuInfo().then(res => {
// 对二级菜单进行排序,把同一一级菜单放在一块
// 取得树形结构数组
this.menuData = this.arrayToJson(res.rows)
// 取出所有二级菜单
this.allMenus = []
for (var i = 0, len = this.menuData.length; i < len; i++) {
if (this.menuData[i].children) {
this.allMenus = this.allMenus.concat(this.menuData[i].children)
}
}
// 菜单中并入操作权限以及选中数组
for (var k = 0, l = this.allMenus.length; k < l; k++) {
for (var j = 0, len2 = this.handles.length; j < len2; j++) {
if (this.handles[j].Parentcode === this.allMenus[k].code) {
if (!this.allMenus[k].handle) {
this.$set(this.allMenus[k], 'handle', [])
this.allMenus[k].handle.push(this.handles[j])
} else {
this.allMenus[k].handle.push(this.handles[j])
}
if (!this.allMenus[k].checked) {
this.$set(this.allMenus[k], 'checked', [])
}
}
}
}
// 合并的方法
this.merage()
// 要等数据全部渲染出来再使用默认选中,所以要用nextTick,否则不起作用
this.$nextTick(() => {
this.getPowerMenu()
})
})
},
// 数组转换为树形结构数据
arrayToJson(treeArray) {
var r = []
var tmpMap = {}
for (var i = 0, l = treeArray.length; i < l; i++) {
// 以每条数据的id作为obj的key值,数据作为value值存入到一个临时对象里面
tmpMap[treeArray[i]['code']] = treeArray[i]
}
for (i = 0, l = treeArray.length; i < l; i++) {
var key = tmpMap[treeArray[i]['parentcode']]
// 循环每一条数据的pid,假如这个临时对象有这个key值,就代表这个key对应的数据有children,需要Push进去
if (key) {
if (!key['children']) {
key['children'] = []
key['children'].push(treeArray[i])
} else {
key['children'].push(treeArray[i])
}
} else {
// 如果没有这个Key值,那就代表没有父级,直接放在最外层
r.push(treeArray[i])
}
}
return r
},
// 单元格合并方法
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
// 该数组表示:第一行合并一个数据,第二行合并十个数据,被合并项全部置0,第三个一级菜单合并6个数据,被合并项全部置0,以此类推....
// this.menu1Arr: [1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 6, 0, 0, 0, 0, 0, 2, 0, 2, 0, 7, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 6, 0, 0, 0, 0, 0, 2, 0]
//
// 第三列的合并方法,一级菜单,columnIndex === 2
// 返回的合并数组:第一行第三列:[1,1],第二行第三列:[10,1],第三行第三列[0,0],以此类推...
// [1,1]表示合并1行1列,[10,1]表示合并10行,1列
if (columnIndex === 2) {
const _row_1 = this.menu1Arr[rowIndex]
// 判断该行是为0的被合并行,还是大于0的共同合并行的第一行
const _col_1 = _row_1 > 0 ? 1 : 0 // 如果被合并了_row=0则它这个列需要取消
return {
rowspan: _row_1,
colspan: _col_1
}
}
},
// 要合并的数组的方法,,该方法主要目的是循环整个表格数据,从第一个数据开始,如果相邻的数据属于同一个一级菜单,则设置合并项加1,被合并的项设置为0,最终结果如上的数组this.menu1Arr
merage() {
// 初始化一级菜单的合并行的数组
this.menu1Arr = []
this.menu1Pos = 0
for (var i = 0; i < this.allMenus.length; i++) {
if (i === 0) {
// 第一行必须存在
this.menu1Arr.push(1)
this.menu1Pos = 0
} else {
// 判断当前元素与上一个元素是否相同 this.menu1Pos是menu1Arr内容的序号
// 一级菜单
if (this.allMenus[i].parentcode === this.allMenus[i - 1].parentcode) {
this.menu1Arr[this.menu1Pos] += 1
this.menu1Arr.push(0)
} else {
this.menu1Arr.push(1)
this.menu1Pos = i
}
}
}
},
/** 加载默认选中授权部分 */
// 查看授权菜单时获取已授权的菜单数据
getPowerMenu() {
},
// 获取已授权操作数据
lookPowerGisInfo() {
},
// 全选单选多选菜单
selsChange(sels) {
},
// 操作权限全选
AllSelect() {
},
// 取消操作权限全选
cancelAllSelect() {
},
// 保存授权
savePower() {
}
}
}
</script>
<style scoped>
.topbox{
display: flex;
justify-content: space-between;
}
</style>
三、使用elementui表格注意的问题
1.表格中不能使用this调用vue的data中的数据,如下:不能使用this调用handle,否则会报错undefined,非表格中可以,如下:
2.在表格数据的组合使用中,可能会遇到两组数据组合后渲染不出来的问题,可能是等数据渲染出来再组合,则可以渲染出来,如下,使用vue的$nextTick
// 要等数据全部渲染出来再使用默认选中,所以要用nextTick,否则不起作用
this.$nextTick(() => {
this.getPowerMenu()
})
3.解决elementui的tooltip显示过长的问题:
在全局加入样式:
.el-tooltip__popper {
max-width: 400px;
line-height: 180%;
}