基于vue+element的table横向树形结构

需求:

  1. 指定需要合并的列,相同数据向下合并形成树节点
  2. 相同数据向下合并时不能跨越节点

github地址,喜欢star

<!-- table部分 -->
<el-table v-if="this.spanMethod.length" ref="table" :data="testTableArr" :span-method="arraySpanMethod" class="ele-table table-info-area" border stripe>
  <el-table-column :prop="item" :label="tableTitle[item].name+info[tableTitle[item].type]" align="center" v-for="(item,index) in tableTitleKey" :key="index"></el-table-column>
</el-table>
data() {
    return {
        info: {
            string: '',
            avg: '(平均值)',
            sum: '(总数)'
        },
        testTableArr: [], // table数据
        spanKey: [], // 需要合并的列,每个元素为表格的prop值(键值)
        tableTitle: {}, // table表头显示  
        tableTitleKey: [], // 所有的列的prop值(键值)
        spanMethod: [], // 表格向下合并的方式
        divArr: [], // 分片数据,用于将数据分片,保证不会
        divIndex: [0], // 用于记录分片的位置
    }
},
methods: {
      /**
       * 合并表格
       */
      arraySpanMethod({ row, column, rowIndex, columnIndex }) {
        if (this.spanKey.length) {
          for (let keyIndex = 0; keyIndex < this.spanKey.length; keyIndex++) {
            // 找到指定需要合并的列,应用合并规则
            if (this.spanKey[keyIndex] === this.tableTitleKey[columnIndex]) {
              const _row = this.spanMethod[keyIndex][rowIndex];
              const _col = _row > 0 ? 1 : 0;
              return {
                rowspan: _row,
                colspan: _col
              }
            }
          }
        } else {
          return {
            rowspan: 1,
            colspan: 1
          }
        }
      },
      /**
       * data为传入的表格数据,结构为[{},{}]
       * spanKey为需要合并操作的列  结构为[]
       */
      normalizeData(data,spanKey) {
        this.spanMethod = [];
        this.divIndex = [0];
        // 有需要合并的字段才做处理
        if (spanKey.length) {
          for (let keyIndex = 0; keyIndex < spanKey.length; keyIndex++) {
            const key = spanKey[keyIndex];
            this.sliceData()
            this.spanMethod.push(this.spanKeyMenthod(key))
          }
        }
      },

      /**
       * key 为指定列的键值
       * contactArr 指定的列下 行的合并方式   [] 
       * contactDot 单元格合并展示位
       */
      spanKeyMenthod(key) {
        let divContactArr = [] // 记录当前列的向下合并方式
        // 计算每一片单独的行扩展方式
        let divIndexTemp = [...this.divIndex] 
        // 重点: 记录每次循环的上一次分片位置,目的是让当前位置index插入在分片中   eg:[0,6,20]
        for (const itemIndex in this.divArr) {
          let divArrItem = this.divArr[itemIndex]
          let contactArr = [];
          let contactDot = 0;
          divArrItem.map((item,index) => {
            if (index == 0) {
              contactArr.push(1);
              contactDot = 0;
            } else {
              // 不是第一行的情况下比较和上一行的值
              if (item[key] === divArrItem[index-1][key]) {
                // 值相同则放入0,第一个相同的合并方式数组加一
                contactArr[contactDot] += 1
                contactArr.push(0)
              } else {
                contactArr.push(1);
                contactDot = index;
                // 记录分片的位置
                this.divIndex.push(index+divIndexTemp[itemIndex])
                // 重点:插入分片中    eg:第一块分片位置index在0,6中插入   [0,2,3,5,6,20]  第二块分片位置index在6,20中插入[0,2,3,5,6,8,11,15,20]
                this.divIndex.sort((a,b)=>{
                  return a - b
                }) // 因为是push进去  所以需要排序
                this.divIndex = [...new Set(this.divIndex)]   // 去重
              }
            }
          })
          divContactArr = divContactArr.concat(contactArr)
        }
        return divContactArr;
      },
      /**
       * 将数据分片,防止数据向下合并的时候跨级
       */
      sliceData() {
        this.divArr = []
        for (let index = 0; index < this.divIndex.length; index++) {
          if (index == this.divIndex.length-1) {
            // 如果最后一个则截取到数据最末尾
            this.divArr.push(this.testTableArr.slice(this.divIndex[index]))
          } else {
            // 截取两个分片位置之间的数据
            this.divArr.push(this.testTableArr.slice(this.divIndex[index],this.divIndex[index+1]))
          }
        }
      }
}
效果图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,256评论 0 9
  • 一些概念 数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算,而且确保经过这...
    Winterfell_Z阅读 5,710评论 0 13
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,833评论 0 5
  • 原文地址Dynamo 摘要 面对世界上最大的电商网站 Amazon.com,我们遇到的最大挑战之一就是海量规模下后...
    wangjie_yy阅读 2,178评论 0 3
  • 原创: 红尘闲云 闲云醉语 云间,是我书房的斋号。 云间客,皆为我的座上宾。 亲爱的们,请坐,看茶。 人生路上,有...
    红尘闲云阅读 475评论 0 0