詳解vue-cli+element-ui樹形表格(多級表格折騰小計(jì))
前沿
最近在項(xiàng)目開發(fā)中需要做一個(gè)多級表格,樹形表格的功能,看看element-ui上沒有,自己開是折騰,話不多說,上思路和代碼。
效果圖:

可點(diǎn)擊收縮,展開。
一,首先創(chuàng)建一個(gè)公共的文件夾treeTable,里邊放一個(gè)index.vue和eval.js
先看看index.vue,原理就是在element-ui的基礎(chǔ)上做了進(jìn)一步改造。
//利用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: {
// 格式化數(shù)據(jù)源
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
},
// 圖標(biāo)顯示
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: '時(shí)間線',
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ù)使用
寫在前面
此組件僅提供一個(gè)創(chuàng)建TreeTable的解決思路
prop說明
data
必填
原始數(shù)據(jù),要求是一個(gè)數(shù)組或者對象
[{
key1: value1,
key2: value2,
children: [{
key1: value1
},
{
key1: value1
}]
},
{
key1: value1
}]
或者
{
key1: value1,
key2: value2,
children: [{
key1: value1
},
{
key1: value1
}]
}
columns
列屬性,要求是一個(gè)數(shù)組
text: 顯示在表頭的文字
value: 對應(yīng)data的key。treeTable將顯示相應(yīng)的value
width: 每列的寬度,為一個(gè)數(shù)字(可選)
如果你想要每個(gè)字段都有自定義的樣式或者嵌套其他組件,columns可不提供,直接像在el-table一樣寫即可,如果沒有自定義內(nèi)容,提供columns將更加的便捷方便
如果你有幾個(gè)字段是需要自定義的,幾個(gè)不需要,那么可以將不需要自定義的字段放入columns,將需要自定義的內(nèi)容放入到slot中,詳情見后文
[{
value:string,
text:string,
width:number
},{
value:string,
text:string,
width:number
}]
expandAll
是否默認(rèn)全部展開,boolean值,默認(rèn)為false
evalFunc
解析函數(shù),function,非必須
如果不提供,將使用默認(rèn)的evalFunc
evalArgs
解析函數(shù)的參數(shù),是一個(gè)數(shù)組
請注意,自定義的解析函數(shù)參數(shù)第一個(gè)為this.data,第二個(gè)參數(shù)為, this.expandAll,你不需要在evalArgs填寫。一定記住,這兩個(gè)參數(shù)是強(qiáng)制性的,并且位置不可顛倒 this.data為需要解析的數(shù)據(jù),this.expandAll為是否默認(rèn)展開
如你的解析函數(shù)需要的參數(shù)為(this.data, this.expandAll,1,2,3,4),那么你只需要將[1,2,3,4]賦值給evalArgs就可以了
如果你的解析函數(shù)參數(shù)只有(this.data, this.expandAll),那么就可以不用填寫evalArgs了
slot
這是一個(gè)自定義列的插槽。
默認(rèn)情況下,treeTable只有一行行展示數(shù)據(jù)的功能。但是一般情況下,我們會要給行加上一個(gè)操作按鈕或者根據(jù)當(dāng)行數(shù)據(jù)展示不同的樣式,這時(shí)我們就需要自定義列了。
slot和columns屬性可同時(shí)存在,columns里面的數(shù)據(jù)列會在slot自定義列的左邊展示
其他
如果有其他的需求,請參考el-table的api自行修改index.vue
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲
這篇文章主要介紹了VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲,需要的朋友可以參考下本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-04-04
vue $nextTick實(shí)現(xiàn)原理深入詳解
這篇文章主要介紹了vue $nextTick實(shí)現(xiàn)原理深入詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
利用vue組件自定義v-model實(shí)現(xiàn)一個(gè)Tab組件方法示例
這篇文章主要給大家介紹了關(guān)于利用vue組件自定義v-model實(shí)現(xiàn)一個(gè)Tab組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
vue關(guān)于接口請求數(shù)據(jù)過大導(dǎo)致瀏覽器崩潰的問題
這篇文章主要介紹了vue關(guān)于接口請求數(shù)據(jù)過大導(dǎo)致瀏覽器崩潰的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
Vue?watch中監(jiān)聽值的變化,判斷后修改值方式
這篇文章主要介紹了Vue?watch中監(jiān)聽值的變化,判斷后修改值方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04

