使用element ui组件库实现一个table的两棵树的效果

效果如下,左边树自动展开一级,右边树默认显示楼层,然后可以一个个展开

element ui改写实现两棵树-LMLPHP

代码如下

 <el-table :data="relativeData"
:fit="isFit"
height="700px"
:row-style="showTr"
:row-class-name="tableRowClassName"
:header-row-class-name="tableRowClassName"
size="small"
highlight-current-row>
<el-table-column fixed
width=""
show-overflow-tooltip
style="max-width:310px;">
<template slot="header">
<div class="monitor_header">
<div class="monitor_item">分项名称</div>
<div class="line_item"></div>
<div class="building_item">建筑空间</div>
</div>
</template>
<template slot-scope="scope">
<template v-if="spaceIconShow()">
<span v-for="(space, levelIndex) in scope.row._level"
class="ms-tree-space"
:key="levelIndex"></span>
</template> <span class="button"
v-if="toggleIconShow(scope.row)"
@click="toggle(scope.$index)">
<i v-if="!scope.row._expanded"
class="el-icon-plus"
aria-hidden="true"></i>
<i v-if="scope.row._expanded"
class="el-icon-minus"
aria-hidden="true"></i>
</span>
<span class="ms-tree-space"></span>
{{scope.row.name}}
<div class="table_tree_icons"> <i class="plus_icon"
@click.stop="addMonitorDailog(scope.row,$event)"></i>
<i class="edit_icon"
@click.stop="updateMonitorDailog(scope.row,$event)"></i>
<i class="delete_icon"
v-if="scope.row.parentNodeId!='0'"
@click.stop="
deleteMonitor(scope.row,$event)"></i></div>
</template>
</el-table-column>
<el-table-column v-for="(building,index) in spaceTreeData2"
:key="index"
show-overflow-tooltip
:label="building.name">
<template slot="header">
<!-- <i class="el-icon-plus"
style="color:#ddd;margin-right:5px;cursor:pointer"
@click="toggleExpandFloor(building.id,$event)"></i> -->
<div>{{building.name}}</div>
</template>
<el-table-column width=""
show-overflow-tooltip>
<el-table-column width=""
show-overflow-tooltip>
<template slot-scope="scope">
<template v-if="!(scope.row.relatives.some(item => {if(item.spaceId==building.id){return true;}}))">
<span class="row-column-express"
@click.stop="addExpress(scope.row,building.id,$event)">--</span>
</template>
<template v-for=" (item,index) in scope.row.relatives">
<span class="row-column-express"
:key="index"
v-if="item.spaceId==building.id"
@click.stop="updateExpress(item,$event)">{{ item.expression }}</span>
</template>
</template>
</el-table-column>
</el-table-column>
<template v-if="showFloor &&building.children&& building.children.length>0">
<!-- :render-header="renderHeaderSecond" -->
<el-table-column v-for="(floor,findex) in building.children"
:key="findex"
show-overflow-tooltip
:label="floor.name"
width="">
<template slot="header"
slot-scope="scope">
<div><i class="el-icon-plus"
@click="expandFloorInfo(scope,floor,$event)"></i><span>{{floor.name}}</span></div>
</template>
<el-table-column width=""
show-overflow-tooltip>
<template slot-scope="scope">
<template v-if="!(scope.row.relatives.some(item => {if(item.spaceId==floor.id){return true;}}))">
<span class="row-column-express"
@click.stop="addExpress(scope.row,floor.id,$event)">--</span>
</template>
<template v-for=" (item,index3) in scope.row.relatives">
<span class="row-column-express"
:key="index3"
v-if="item.spaceId==floor.id"
@click.stop="updateExpress(item,$event)">{{ item.expression }}</span>
</template> </template>
</el-table-column>
<template v-if="floor.children && floor.children.length>0">
<el-table-column v-for="(room,index2) in floor.children"
show-overflow-tooltip
:key="index2"
:label="room.name"
width="">
<template slot-scope="scope">
<template v-if="!(scope.row.relatives.some(item => {if(item.spaceId==room.id){return true;}}))">
<span class="row-column-express"
@click.stop="addExpress(scope.row,room.id,$event)">--</span>
</template>
<template v-for=" (item,index4) in scope.row.relatives">
<span class="row-column-express"
:key="index4"
v-if="item.spaceId==room.id"
@click.stop="updateExpress(item,$event)">{{ item.expression }}</span>
</template> </template>
</el-table-column> </template>
</el-table-column>
</template>
</el-table-column>
</el-table>

数据层

  props: {
//左边分项树的内容
monitorRelativeData: {
type: Array
},
//头部空间树的数据
spaceTreeData: {
type: Array
}
},
data() {
return {
expandRowKeys: [], //默认展开的节点
isFit: false, //table是否自适应
roomList: []//为了控制房间的显示,存储房间集合
}
},
computed: {
//数据的处理,每条数据是否展开,父节点信息等
relativeData() {
let data = MSDataTransfer.treeToArray(this.monitorRelativeData, null, null, true)
return data
},
//只存储楼层,房间另外存储
spaceTreeData2() {
var res = this.spaceTreeData
var roomList = []
if (res.length == || !res[].children) {
return []
}
res[].children = this.spaceTreeData[].children.map(function(item) {
item.len = item.children ? item.children.length :
if (item.len > ) {
roomList = roomList.concat(item.children)
}
item.children = []
return item
})
this.roomList = roomList
return res
},
buildingId() {
return this.$store.getters.buildingId
}
},
MSDataTransfer.treeToArray是把tree的层级关系进行处理  加入 _expanded属性,_parent父节点属性,_level层级关系
// 数据转换
DataTransfer.treeToArray = function(data, parent, level, expandedAll) {
let tmp = [];
Array.from(data).forEach(function(record) {
if (record._expanded === undefined) {
Vue.set(record, "_expanded", expandedAll);
}
if (parent) {
Vue.set(record, "_parent", parent);
}
let _level = ;
if (level !== undefined && level !== null) {
_level = level + ;
}
Vue.set(record, "_level", _level);
tmp.push(record);
if (record.children && record.children.length > ) {
let children = DataTransfer.treeToArray(
record.children,
record,
_level,
expandedAll
);
tmp = tmp.concat(children);
}
}); return tmp;
};
MSDataTransfer.treeToArray处理左边树的时候是,默认展开所有,然后在每次操作的时候,都对树的是否展开状态进行更改
 updated() {
this.toggleAll()
},
methods: {
//test add
spaceIconShow(index) {
return true
},
toggleIconShow(record) {
if (record.children && record.children.length > ) {
return true
}
return false
},
toggle(trIndex) {
let record = this.relativeData[trIndex]
record._expanded = !record._expanded
//展开的数据节点
if (record._expanded) {
this.expandRowKeys.push(record.id)
} else {
var expandRowKeys = []
this.expandRowKeys.forEach(function(item) {
if (item != record.id) {
expandRowKeys.push(item)
}
})
this.expandRowKeys = expandRowKeys
}
},
showTr(rows, index) {
let row = rows.row
let show = row._parent ? row._parent._expanded && row._parent._show : true
row._show = show
return show ? '' : 'display:none;'
},
toggleAll() {
/**
* i 从1开始,不收起第一级节点
*/
for (let i = ; i < this.relativeData.length; i++) {
let record = this.relativeData[i]
if (this.expandRowKeys.indexOf(record.id) == -) {
record._expanded = false
}
}
console.log('toggleAll', this.relativeData)
},/**关闭房间 */
expandFloorInfo(row, floor, event) {
if (floor.len > && floor.children.length == ) {
var roomList = this.roomList
for (var i = ; i < roomList.length; i++) {
if (roomList[i].parentNodeId && roomList[i].parentNodeId == floor.nodeId) {
floor.children.push(roomList[i])
if (floor.len == floor.children.length) {
break
}
}
}
this.expandFloorInfo(row, floor, event)
return
}
var column = row.column
console.log('column', column)
var len = floor.children.length
var columnArr = column.id.split('_')
var num = columnArr[columnArr.length - ]
columnArr.pop()
columnArr.pop()
var tableClass = columnArr.join('_')
console.log('tableClass', tableClass)
num++
//展开
if (event.target.className == 'el-icon-plus') {
event.target.className = 'el-icon-minus'
event.target.parentNode.parentNode.parentNode.colSpan = len +
JQuery('.' + tableClass)[].colSpan += len
JQuery('.el-table table.el-table__header').css('cssText', 'width:310px !important')
JQuery('.el-table table.el-table__body').css('cssText', 'width:310px!important')
JQuery('[name^=' + column.id + '_]').show()
JQuery('[class^=' + column.id + '_]').show()
} else {
//收缩
event.target.className = 'el-icon-plus'
JQuery('[name^=' + column.id + '_]').hide()
JQuery('[class^=' + column.id + '_]').hide()
JQuery('[name^=' + column.id + '_column_' + num + ']').show()
JQuery('[class^=' + column.id + '_column_' + num + ']').show()
event.target.parentNode.parentNode.parentNode.colSpan =
JQuery('.' + tableClass)[].colSpan -= len
JQuery('.el-table table.el-table__body').css('cssText', 'width:310px !important')
JQuery('.el-table table.el-table__header').css('cssText', 'width:310px !important')
}
},
}
04-27 05:30