一、固定数据和已知合并行列数的合并

以下分别设置了合并一行和合并多个一行的的表格合并方法

<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%;
}
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐