element ui改写实现两棵树
使用element ui组件库实现一个table的两棵树的效果
效果如下,左边树自动展开一级,右边树默认显示楼层,然后可以一个个展开
代码如下
<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="310" 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="120" show-overflow-tooltip> <el-table-column width="120" 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="120"> <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="120" 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="120"> <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 == 0 || !res[0].children) { return [] } res[0].children = this.spaceTreeData[0].children.map(function(item) { item.len = item.children ? item.children.length : 0 if (item.len > 0) { 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 = 0; if (level !== undefined && level !== null) { _level = level + 1; } Vue.set(record, "_level", _level); tmp.push(record); if (record.children && record.children.length > 0) { 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 > 0) { 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 = 1; i < this.relativeData.length; i++) { let record = this.relativeData[i] if (this.expandRowKeys.indexOf(record.id) == -1) { record._expanded = false } } console.log('toggleAll', this.relativeData) },/**关闭房间 */ expandFloorInfo(row, floor, event) { if (floor.len > 0 && floor.children.length == 0) { var roomList = this.roomList for (var i = 0; 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 - 1] 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 + 1 JQuery('.' + tableClass)[0].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 = 1 JQuery('.' + tableClass)[0].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') } },
}