树表格的实现

有时候我们会遇到表格树的展示,类似于下图的需求:

 

其中组件的封装主要在table-tree文件夹内:

main.vue的内容如下:

  1 <template>
  2   <el-table :data="formatData"
  3             :stripe="option.stripe"
  4             :row-style="showRow"
  5             :row-class-name="rowClassName"
  6             v-bind="$attrs"
  7             :border="border">
  8     <el-table-column v-if="columns.length===0"
  9                      width="150">
 10       <template slot-scope="scope">
 11         <span v-for="space in scope.row._level"
 12               class="ms-tree-space"
 13               :key="space"></span>
 14         <span class="tree-ctrl"
 15               v-if="iconShow(0,scope.row)"
 16               @click="toggleExpanded(scope.$index)">
 17           <i v-if="!scope.row._expanded"
 18              class="el-icon-plus"></i>
 19           <i v-else
 20              class="el-icon-minus"></i>
 21         </span>
 22         {{scope.$index}}
 23       </template>
 24     </el-table-column>
 25     <el-table-column v-else
 26                      v-for="(column, index) in columns"
 27                      :key="column.value"
 28                      :label="column.text"
 29                      :width="column.width">
 30       <template slot-scope="scope">
 31         <span v-if="index === 0"
 32               v-for="space in scope.row._level"
 33               class="ms-tree-space"
 34               :key="space"></span>
 35         <span class="tree-ctrl"
 36               v-if="iconShow(index,scope.row)"
 37               @click="toggleExpanded(scope.$index)">
 38           <i v-if="!scope.row._expanded"
 39              class="el-icon-plus"></i>
 40           <i v-else
 41              class="el-icon-minus"></i>
 42         </span>
 43         {{scope.row[column.value]}}
 44       </template>
 45     </el-table-column>
 46     <slot></slot>
 47   </el-table>
 48 </template>
 49 
 50 <script>
 51 import treeToArray from "./eval";
 52 export default {
 53   name: "AvueTreeTable",
 54   props: {
 55     option: {
 56       type: Object,
 57       required: true
 58     },
 59     rowClassName: Function,
 60     evalFunc: Function,
 61     evalArgs: Array
 62   },
 63   data() {
 64     return {};
 65   },
 66   created() {},
 67   computed: {
 68     data: function() {
 69       return this.option.data || [];
 70     },
 71     columns: function() {
 72       return this.option.columns || [];
 73     },
 74     expandAll: function() {
 75       return this.option.expandAll;
 76     },
 77     border: function() {
 78       return this.option.border || true;
 79     },
 80     // 格式化数据源
 81     formatData: function() {
 82       let tmp;
 83       if (!Array.isArray(this.data)) {
 84         tmp = [this.data];
 85       } else {
 86         tmp = this.data;
 87       }
 88       const func = this.evalFunc || treeToArray;
 89       const args = this.evalArgs
 90         ? Array.concat([tmp, this.expandAll], this.evalArgs)
 91         : [tmp, this.expandAll];
 92       return func.apply(null, args);
 93     }
 94   },
 95   methods: {
 96     showRow: function(row) {
 97       const show = row.row.parent
 98         ? row.row.parent._expanded && row.row.parent._show
 99         : true;
100       row.row._show = show;
101       return show
102         ? "animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;"
103         : "display:none;";
104     },
105     // 切换下级是否展开
106     toggleExpanded: function(trIndex) {
107       const record = this.formatData[trIndex];
108       record._expanded = !record._expanded;
109     },
110     // 图标显示
111     iconShow(index, record) {
112       return index === 0 && record.children && record.children.length > 0;
113     }
114   }
115 };
116 </script>
117 <style rel="stylesheet/css">
118 @keyframes treeTableShow {
119   from {
120     opacity: 0;
121   }
122   to {
123     opacity: 1;
124   }
125 }
126 @-webkit-keyframes treeTableShow {
127   from {
128     opacity: 0;
129   }
130   to {
131     opacity: 1;
132   }
133 }
134 </style>
135 
136 <style lang="scss" rel="stylesheet/scss" scoped>
137 $color-blue: #2196f3;
138 $space-width: 18px;
139 .ms-tree-space {
140   position: relative;
141   top: 1px;
142   display: inline-block;
143   font-style: normal;
144   font-weight: 400;
145   line-height: 1;
146   width: $space-width;
147   height: 14px;
148   &::before {
149     content: "";
150   }
151 }
152 .processContainer {
153   width: 100%;
154   height: 100%;
155 }
156 table td {
157   line-height: 26px;
158 }
159 
160 .tree-ctrl {
161   position: relative;
162   cursor: pointer;
163   color: $color-blue;
164   margin-left: -$space-width;
165 }
166 </style>
View Code

eval.js的内容如下:

 1 /**
 2 * @Author: jianglei
 3 * @Date:   2017-10-12 12:06:49
 4 */
 5 'use strict'
 6 import Vue from 'vue'
 7 export default function treeToArray(data, expandAll, parent = null, level = null) {
 8   let tmp = []
 9   Array.from(data).forEach(function(record) {
10     if (record._expanded === undefined) {
11       Vue.set(record, '_expanded', expandAll)
12     }
13     let _level = 1
14     if (level !== undefined && level !== null) {
15       _level = level + 1
16     }
17     Vue.set(record, '_level', _level)
18     // 如果有父元素
19     if (parent) {
20       Vue.set(record, 'parent', parent)
21     }
22     tmp.push(record)
23     if (record.children && record.children.length > 0) {
24       const children = treeToArray(record.children, expandAll, record, _level)
25       tmp = tmp.concat(children)
26     }
27   })
28   return tmp
29 }
View Code

index.js的内容如下:

1 import TableTree from './src/main';
2 
3 /* istanbul ignore next */
4 TableTree.install = function(Vue) {
5     Vue.component(TableTree.name, TableTree);
6 };
7 
8 export default TableTree;
View Code

在其他组件内只需要引入main.vue即可,

js中option变量为:

  1 option: {
  2         expandAll: true,
  3         columns: [
  4           {
  5             text: '事件',
  6             value: 'event',
  7             width: 200
  8           },
  9           {
 10             text: 'ID',
 11             value: 'id'
 12           },
 13           {
 14             text: '时间线',
 15             value: 'timeLine'
 16           },
 17           {
 18             text: '备注',
 19             value: 'comment'
 20           }
 21         ],
 22         data: [
 23           {
 24             id: 0,
 25             event: '事件1',
 26             timeLine: 50,
 27             comment: '无'
 28           },
 29           {
 30             id: 1,
 31             event: '事件1',
 32             timeLine: 100,
 33             comment: '无',
 34             children: [
 35               {
 36                 id: 2,
 37                 event: '事件2',
 38                 timeLine: 10,
 39                 comment: '无'
 40               },
 41               {
 42                 id: 3,
 43                 event: '事件3',
 44                 timeLine: 90,
 45                 comment: '无',
 46                 children: [
 47                   {
 48                     id: 4,
 49                     event: '事件4',
 50                     timeLine: 5,
 51                     comment: '无'
 52                   },
 53                   {
 54                     id: 5,
 55                     event: '事件5',
 56                     timeLine: 10,
 57                     comment: '无'
 58                   },
 59                   {
 60                     id: 6,
 61                     event: '事件6',
 62                     timeLine: 75,
 63                     comment: '无',
 64                     children: [
 65                       {
 66                         id: 7,
 67                         event: '事件7',
 68                         timeLine: 50,
 69                         comment: '无',
 70                         children: [
 71                           {
 72                             id: 71,
 73                             event: '事件71',
 74                             timeLine: 25,
 75                             comment: 'xx'
 76                           },
 77                           {
 78                             id: 72,
 79                             event: '事件72',
 80                             timeLine: 5,
 81                             comment: 'xx'
 82                           },
 83                           {
 84                             id: 73,
 85                             event: '事件73',
 86                             timeLine: 20,
 87                             comment: 'xx'
 88                           }
 89                         ]
 90                       },
 91                       {
 92                         id: 8,
 93                         event: '事件8',
 94                         timeLine: 25,
 95                         comment: '无'
 96                       }
 97                     ]
 98                   }
 99                 ]
100               }
101             ]
102           }
103         ]
104       }
View Code

哈哈哈,这样就实现了表格树

但是有时候我们要自定义表格的列,如下图:

 

 实现方式如下(底层封装组件不变,只是在引用的组件内做些改变即可):

 1 <tree-table :option="option">
 2         <el-table-column label="事件">
 3           <template slot-scope="scope">
 4             <span style="color:sandybrown">{{scope.row.event}}</span>
 5             <el-tag>{{scope.row.timeLine+'ms'}}</el-tag>
 6           </template>
 7         </el-table-column>
 8         <el-table-column label="时间线">
 9           <template slot-scope="scope">
10             <el-tooltip effect="dark"
11                         :content="scope.row.timeLine+'ms'"
12                         placement="left">
13               <div class="processContainer">
14                 <div class="process"
15                      :style="{ width:scope.row._width * 500+'px',
16               background:scope.row._width>0.5?'rgba(233,0,0,.5)':'rgba(0,0,233,0.5)',
17               marginLeft:scope.row._marginLeft * 500+'px' }">
18                   <span style="display:inline-block"></span>
19                 </div>
20               </div>
21             </el-tooltip>
22           </template>
23         </el-table-column>
24         <el-table-column label="操作"
25                          width="200">
26           <template slot-scope="scope">
27             <el-button type="text"
28                        @click="message(scope.row)">点击</el-button>
29           </template>
30         </el-table-column>
31       <tree-table>
View Code
 1 option: {
 2         data: {
 3           id: 1,
 4           event: '事件1',
 5           timeLine: 100,
 6           comment: '无',
 7           children: [
 8             {
 9               id: 2,
10               event: '事件2',
11               timeLine: 10,
12               comment: '无'
13             },
14             {
15               id: 3,
16               event: '事件3',
17               timeLine: 90,
18               comment: '无',
19               children: [
20                 {
21                   id: 4,
22                   event: '事件4',
23                   timeLine: 5,
24                   comment: '无'
25                 },
26                 {
27                   id: 5,
28                   event: '事件5',
29                   timeLine: 10,
30                   comment: '无'
31                 },
32                 {
33                   id: 6,
34                   event: '事件6',
35                   timeLine: 75,
36                   comment: '无',
37                   children: [
38                     {
39                       id: 7,
40                       event: '事件7',
41                       timeLine: 50,
42                       comment: '无',
43                       children: [
44                         {
45                           id: 71,
46                           event: '事件71',
47                           timeLine: 25,
48                           comment: 'xx'
49                         },
50                         {
51                           id: 72,
52                           event: '事件72',
53                           timeLine: 5,
54                           comment: 'xx'
55                         },
56                         {
57                           id: 73,
58                           event: '事件73',
59                           timeLine: 20,
60                           comment: 'xx'
61                         }
62                       ]
63                     },
64                     {
65                       id: 8,
66                       event: '事件8',
67                       timeLine: 25,
68                       comment: '无'
69                     }
70                   ]
71                 }
72               ]
73             }
74           ]
75         }
76       }
View Code

 

posted @ 2018-08-16 15:52  yuwenjing  阅读(2591)  评论(0编辑  收藏  举报