vue-cli + element-ui 樹形表格(多級表格折騰小計)

前沿

最近在項目開發(fā)中需要做一個多級表格,樹形表格的功能盆色,看看element-ui上沒有灰蛙,自己開是折騰,話不多說隔躲,上思路和代碼摩梧。
效果圖:


基于vue的多級表格.png

可點擊收縮,展開宣旱。

一仅父,首先創(chuàng)建一個公共的文件夾treeTable,里邊放一個index.vue和eval.js

先看看index.vue,原理就是在element-ui的基礎上做了進一步改造。

//利用element-ui的 <template slot-scope="scope">屬性驾霜,在插入多級表格
<template>
  <el-table :data="formatData" :row-style="showRow" v-bind="$attrs">
    <el-table-column v-if="columns.length===0" width="150">
      <template slot-scope="scope">
        <span v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
        <span class="tree-ctrl" v-if="iconShow(0,scope.row)" @click="toggleExpanded(scope.$index)">
          <i v-if="!scope.row._expanded" class="el-icon-plus"></i>
          <i v-else class="el-icon-minus"></i>
        </span>
        {{scope.$index}}
      </template>
    </el-table-column>
    <el-table-column v-else v-for="(column, index) in columns" :key="column.value" :label="column.text" :width="column.width">
      <template slot-scope="scope">
        <span v-if="index === 0" v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
        <span class="tree-ctrl" v-if="iconShow(index,scope.row)" @click="toggleExpanded(scope.$index)">
          <i v-if="!scope.row._expanded" class="el-icon-plus"></i>
          <i v-else class="el-icon-minus"></i>
        </span>
        {{scope.row[column.value]}}
      </template>
    </el-table-column>
    <slot></slot>
  </el-table>
</template>

<script>
import treeToArray from './eval'
export default {
  name: 'treeTable',
  props: {
    data: {
      type: [Array, Object],
      required: true
    },
    columns: {
      type: Array,
      default: () => []
    },
    evalFunc: Function,
    evalArgs: Array,
    expandAll: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    // 格式化數據源
    formatData: function() {
      let tmp
      if (!Array.isArray(this.data)) {
        tmp = [this.data]
      } else {
        tmp = this.data
      }
      const func = this.evalFunc || treeToArray
      const args = this.evalArgs ? Array.concat([tmp, this.expandAll], this.evalArgs) : [tmp, this.expandAll]
      return func.apply(null, args)
    }
  },
  methods: {
    showRow: function(row) {
      const show = (row.row.parent ? (row.row.parent._expanded && row.row.parent._show) : true)
      row.row._show = show
      return show ? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;' : 'display:none;'
    },
    // 切換下級是否展開
    toggleExpanded: function(trIndex) {
      const record = this.formatData[trIndex]
      record._expanded = !record._expanded
    },
    // 圖標顯示
    iconShow(index, record) {
      return (index === 0 && record.children && record.children.length > 0)
    }
  }
}
</script>
<style rel="stylesheet/css">
  @keyframes treeTableShow {
    from {opacity: 0;}
    to {opacity: 1;}
  }
  @-webkit-keyframes treeTableShow {
    from {opacity: 0;}
    to {opacity: 1;}
  }
</style>

<style lang="scss" rel="stylesheet/scss" scoped>
  $color-blue: #2196F3;
  $space-width: 18px;
  .ms-tree-space {
    position: relative;
    top: 1px;
    display: inline-block;
    font-style: normal;
    font-weight: 400;
    line-height: 1;
    width: $space-width;
    height: 14px;
    &::before {
      content: ""
    }
  }
  .processContainer{
    width: 100%;
    height: 100%;
  }
  table td {
    line-height: 26px;
  }

  .tree-ctrl{
    position: relative;
    cursor: pointer;
    color: $color-blue;
    margin-left: -$space-width;
  }
</style>


eval.js

/**
 * @Author: hyf
 * @Date:   2018-10-27
 */
'use strict'
import Vue from 'vue'
export default function treeToArray(data, expandAll, parent = null, level = null) {
    let tmp = []
    Array.from(data).forEach(function(record) {
        if (record._expanded === undefined) {
            Vue.set(record, '_expanded', expandAll)
        }
        let _level = 1
        if (level !== undefined && level !== null) {
            _level = level + 1
        }
        Vue.set(record, '_level', _level)
            // 如果有父元素
        if (parent) {
            Vue.set(record, 'parent', parent)
        }
        tmp.push(record)
        if (record.children && record.children.length > 0) {
            const children = treeToArray(record.children, expandAll, record, _level)
            tmp = tmp.concat(children)
        }
    })
    return tmp
}

二案训,頁面中的用法

<template>
  <div class="app-container">
    <tree-table :data="data" :columns="columns" border></tree-table>
  </div>
</template>

<script>
import treeTable from '@/components/TreeTable'
export default {
  name: 'treeTableDemo',
  components: { treeTable },
  data() {
    return {
      columns: [
        {
          text: '事件',
          value: 'event',
          width: 200
        },
        {
          text: 'ID',
          value: 'id'
        },
        {
          text: '時間線',
          value: 'timeLine'
        },
        {
          text: '備注',
          value: 'comment'
        }
      ],
      data: [
        {
          id: 0,
          event: '事件1',
          timeLine: 50,
          comment: '無'
        },
        {
          id: 1,
          event: '事件1',
          timeLine: 100,
          comment: '無',
          children: [
            {
              id: 2,
              event: '事件2',
              timeLine: 10,
              comment: '無'
            },
            {
              id: 3,
              event: '事件3',
              timeLine: 90,
              comment: '無',
              children: [
                {
                  id: 4,
                  event: '事件4',
                  timeLine: 5,
                  comment: '無'
                },
                {
                  id: 5,
                  event: '事件5',
                  timeLine: 10,
                  comment: '無'
                },
                {
                  id: 6,
                  event: '事件6',
                  timeLine: 75,
                  comment: '無',
                  children: [
                    {
                      id: 7,
                      event: '事件7',
                      timeLine: 50,
                      comment: '無',
                      children: [
                        {
                          id: 71,
                          event: '事件71',
                          timeLine: 25,
                          comment: 'xx'
                        },
                        {
                          id: 72,
                          event: '事件72',
                          timeLine: 5,
                          comment: 'xx'
                        },
                        {
                          id: 73,
                          event: '事件73',
                          timeLine: 20,
                          comment: 'xx'
                        }
                      ]
                    },
                    {
                      id: 8,
                      event: '事件8',
                      timeLine: 25,
                      comment: '無'
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  }
}
</script>

一下為一些整體思路买置,以及一些說明粪糙,方便后續(xù)使用

寫在前面

此組件僅提供一個創(chuàng)建TreeTable的解決思路

prop說明

data

必填

原始數據,要求是一個數組或者對象

  [{
    key1: value1,
    key2: value2,
    children: [{
      key1: value1
    },
    {
      key1: value1
    }]
  },
  {
    key1: value1
  }]

或者

   {
     key1: value1,
     key2: value2,
     children: [{
       key1: value1
     },
     {
       key1: value1
     }]
   }

columns

列屬性,要求是一個數組

  1. text: 顯示在表頭的文字
  2. value: 對應data的key。treeTable將顯示相應的value
  3. width: 每列的寬度忿项,為一個數字(可選)

如果你想要每個字段都有自定義的樣式或者嵌套其他組件蓉冈,columns可不提供,直接像在el-table一樣寫即可轩触,如果沒有自定義內容寞酿,提供columns將更加的便捷方便

如果你有幾個字段是需要自定義的,幾個不需要脱柱,那么可以將不需要自定義的字段放入columns伐弹,將需要自定義的內容放入到slot中,詳情見后文

[{
  value:string,
  text:string,
  width:number
},{
  value:string,
  text:string,
  width:number
}]

expandAll

是否默認全部展開榨为,boolean值惨好,默認為false

evalFunc

解析函數,function随闺,非必須
如果不提供日川,將使用默認的evalFunc

evalArgs

解析函數的參數,是一個數組

請注意矩乐,自定義的解析函數參數第一個為this.data龄句,第二個參數為, this.expandAll,你不需要在evalArgs填寫散罕。一定記住分歇,這兩個參數是強制性的,并且位置不可顛倒 this.data為需要解析的數據欧漱,this.expandAll為是否默認展開

如你的解析函數需要的參數為(this.data, this.expandAll,1,2,3,4)职抡,那么你只需要將[1,2,3,4]賦值給evalArgs就可以了

如果你的解析函數參數只有(this.data, this.expandAll),那么就可以不用填寫evalArgs了

slot

這是一個自定義列的插槽。

默認情況下硫椰,treeTable只有一行行展示數據的功能繁调。但是一般情況下,我們會要給行加上一個操作按鈕或者根據當行數據展示不同的樣式靶草,這時我們就需要自定義列了蹄胰。

slotcolumns屬性可同時存在,columns里面的數據列會在slot自定義列的左邊展示

其他

如果有其他的需求,請參考el-table的api自行修改index.vue

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末奕翔,一起剝皮案震驚了整個濱河市裕寨,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖宾袜,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捻艳,死亡現場離奇詭異,居然都是意外死亡庆猫,警方通過查閱死者的電腦和手機认轨,發(fā)現死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來月培,“玉大人嘁字,你說我怎么就攤上這事∩夹螅” “怎么了纪蜒?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長此叠。 經常有香客問我纯续,道長,這世上最難降的妖魔是什么灭袁? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任猬错,我火速辦了婚禮,結果婚禮上简卧,老公的妹妹穿的比我還像新娘兔魂。我一直安慰自己,他們只是感情好举娩,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布析校。 她就那樣靜靜地躺著,像睡著了一般铜涉。 火紅的嫁衣襯著肌膚如雪智玻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天芙代,我揣著相機與錄音吊奢,去河邊找鬼。 笑死纹烹,一個胖子當著我的面吹牛页滚,可吹牛的內容都是我干的。 我是一名探鬼主播铺呵,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼裹驰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了片挂?” 一聲冷哼從身側響起幻林,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤贞盯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沪饺,有當地人在樹林里發(fā)現了一具尸體躏敢,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年整葡,在試婚紗的時候發(fā)現自己被綠了件余。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掘宪,死狀恐怖蛾扇,靈堂內的尸體忽然破棺而出攘烛,到底是詐尸還是另有隱情魏滚,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布坟漱,位于F島的核電站鼠次,受9級特大地震影響,放射性物質發(fā)生泄漏芋齿。R本人自食惡果不足惜腥寇,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望觅捆。 院中可真熱鬧赦役,春花似錦、人聲如沸栅炒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赢赊。三九已至乙漓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間释移,已是汗流浹背叭披。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留玩讳,地道東北人涩蜘。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像熏纯,于是被迫代替她去往敵國和親同诫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容