iview的树组件在有默认选中状态的时候默认选中状态的样式改变有bug,默认选中的样式不好看,鉴于此,有renderContent来改造iview的树组件,
效果如图
代码如下
<template> <div class="transfer"> <div class="transfer-left"> <div class="transfer-header"> <h2 class="title">源数据</h2> </div> <div class="transfer-body"> <vue-scroll> <Tree ref="tree" :data="data2" multiple :render="renderContent"> </Tree> </vue-scroll> </div> </div> <div class="transfer-middle"></div> <div class="transfer-right"> <div class="transfer-header"> <h2 class="title">目的数据</h2> </div> <div class="transfer-body"> <ul class="transfer-lists"> <li class="transfer-list" v-for="(item, index) in selectedList" :key="index"> <span class="name">{{item.title}}</span> <Button class="btn-del" icon="md-close" type="text" @click="cancelSelected(item, index)"></Button> </li> </ul> </div> </div> </div> </template> <script> export default { name: 'transfer', data () { return { SelectClass: 'ivu-tree-title ivu-tree-title-selected', DefineClass: 'ivu-tree-title', selectedList: [], selectedData: [ { 'id': 111, 'title': 'leaf 1-1-1' }, { 'id': 112, 'title': 'leaf 1-1-2' } ], data2: [ { id: 1, title: 'parent 1', expand: true, hasChild: true, children: [ { id: 11, title: 'parent 1-1', expand: true, hasChild: true, children: [ { id: 111, title: 'leaf 1-1-1' }, { id: 112, title: 'leaf 1-1-2' } ] }, { id: 12, title: 'parent 1-2', expand: true, hasChild: true, children: [ { id: 121, title: 'leaf 1-2-1' }, { id: 122, title: 'leaf 1-2-2' } ] } ] } ] } }, created () { for (let i = 0, l = this.selectedData.length; i < l; i++) { this.traverseTree(this.data2[0], this.selectedData[i].id, false) } this.selectedList = this.selectedData }, methods: { iconType (hasChild, expand) { let iconType = 'ios-document' if (hasChild) { if (expand) { iconType = 'ios-folder-open' } else { iconType = 'ios-folder' } } else { iconType = 'ios-document' } return iconType }, cancelSelected (item, index) { this.selectedList.splice(index, 1) this.traverseTree(this.data2[0], item.id, true) this.$refs.tree.$el.querySelectorAll('.ivu-tree-title-selected')[index].className = 'ivu-tree-title' }, traverseTree (node, id, isDel) { if (!node) { return } if (node.id === id) { if (isDel) { node.selected = false } else { node.selected = true } } let children = node.children if (children && children.length > 0) { for (let i = 0, l = children.length; i < l; i++) { this.traverseTree(children[i], id, isDel) } } }, renderContent (h, { root, node, data }) { if (node.node.selected) { return h('div', { class: ['ivu-tree-title', 'ivu-tree-title-selected'], on: { click: (e) => { let thisClassName = e.target.className let parentClassName = e.target.parentNode.className if (thisClassName === this.SelectClass || parentClassName === this.SelectClass) { node.node.selected = false if (thisClassName === this.SelectClass) { e.target.className = this.DefineClass } else { e.target.parentNode.className = this.DefineClass } } else { node.node.selected = true if (thisClassName === this.DefineClass) { e.target.className = this.SelectClass } else { e.target.parentNode.className = this.SelectClass } } this.OnSelect(node) } } }, [ h('Icon', { props: { type: this.iconType(node.node.hasChild, node.node.expand) } }), h('span', data.title), h('Icon', { props: { type: 'md-checkmark' } }) ]) } else { return h('div', { class: ['ivu-tree-title'], on: { click: (e) => { let thisClassName = e.target.className let parentClassName = e.target.parentNode.className if (thisClassName === this.SelectClass || parentClassName === this.SelectClass) { node.node.selected = false if (thisClassName === this.SelectClass) { e.target.className = this.DefineClass } else { e.target.parentNode.className = this.DefineClass } } else { node.node.selected = true if (thisClassName === this.DefineClass) { e.target.className = this.SelectClass } else { e.target.parentNode.className = this.SelectClass } } this.OnSelect(node) } } }, [ h('Icon', { props: { type: this.iconType(node.node.hasChild, node.node.expand) } }), h('span', data.title), h('Icon', { props: { type: 'md-checkmark' } }) ]) } }, OnSelect (data) { this.$emit('OnSelectChange', data) this.selectedList = this.$refs.tree.getSelectedNodes() } } } </script> <style lang="scss" scoped> @import './transfer.scss'; </style> <style lang="scss"> .transfer { .ivu-tree-title-selected, .ivu-tree-title-selected:hover, .ivu-tree-title:hover { background-color: #fff; } .ivu-tree-title { vertical-align: middle; span { margin: 0 5px; } .ivu-icon { color: #2b85e4; font-size: 16px; &.ivu-icon-md-checkmark { display: none; } } &.ivu-tree-title-selected { .ivu-icon { &.ivu-icon-md-checkmark { display: inline-block; color: #19be6b; } } } } } </style>
对于节点的点击事件,可以做简单的抽离,js部分代码如下:
export default { name: 'transfer', data () { return { nodeKey: null, SelectClass: 'ivu-tree-title ivu-tree-title-selected', DefineClass: 'ivu-tree-title', selectedList: [], selectedData: [ { 'id': 111, 'title': 'leaf 1-1-1' }, { 'id': 112, 'title': 'leaf 1-1-2' } ], data2: [ { id: 1, title: 'parent 1', expand: true, hasChild: true, children: [ { id: 11, title: 'parent 1-1', expand: true, hasChild: true, children: [ { id: 111, title: 'leaf 1-1-1' }, { id: 112, title: 'leaf 1-1-2' } ] }, { id: 12, title: 'parent 1-2', expand: true, hasChild: true, children: [ { id: 121, title: 'leaf 1-2-1' }, { id: 122, title: 'leaf 1-2-2' } ] } ] } ] } }, created () { for (let i = 0, l = this.selectedData.length; i < l; i++) { this.traverseTree(this.data2[0], this.selectedData[i].id, false) } this.selectedList = this.selectedData }, methods: { iconType (hasChild, expand) { let iconType = 'ios-document' if (hasChild) { if (expand) { iconType = 'ios-folder-open' } else { iconType = 'ios-folder' } } else { iconType = 'ios-document' } return iconType }, cancelSelected (item, index) { this.selectedList.splice(index, 1) this.traverseTree(this.data2[0], item.id, true) this.$refs.tree.$el.querySelectorAll('.ivu-tree-title-selected')[index].className = 'ivu-tree-title' }, renderContent (h, { root, node, data }) { if (node.node.selected) { return h('div', { class: ['ivu-tree-title', 'ivu-tree-title-selected'], on: { click: (e) => { let thisClassName = e.target.className let parentClassName = e.target.parentNode.className let o = this.changeNode(thisClassName, parentClassName) node.node.selected = o.selected if (thisClassName === o.otherClassName) { e.target.className = o.className } else if (parentClassName === o.otherClassName) { e.target.parentNode.className = o.className } this.OnSelect(node) } } }, [ h('Icon', { props: { type: this.iconType(node.node.hasChild, node.node.expand) } }), h('span', data.title), h('Icon', { props: { type: 'md-checkmark' } }) ]) } else { return h('div', { class: ['ivu-tree-title'], on: { click: (e) => { let thisClassName = e.target.className let parentClassName = e.target.parentNode.className let o = this.changeNode(thisClassName, parentClassName) node.node.selected = o.selected if (thisClassName === o.otherClassName) { e.target.className = o.className } else if (parentClassName === o.otherClassName) { e.target.parentNode.className = o.className } this.OnSelect(node) } } }, [ h('Icon', { props: { type: this.iconType(node.node.hasChild, node.node.expand) } }), h('span', data.title), h('Icon', { props: { type: 'md-checkmark' } }) ]) } }, OnSelect (data) { this.$emit('OnSelectChange', data) this.selectedList = this.$refs.tree.getSelectedNodes() }, changeNode (thisClassName, parentClassName) { let selected = false let className = this.DefineClass let otherClassName = this.SelectClass if (thisClassName === this.SelectClass || parentClassName === this.SelectClass) { selected = false className = this.DefineClass otherClassName = this.SelectClass } else { selected = true className = this.SelectClass otherClassName = this.DefineClass } return { selected, className, otherClassName } }, traverseTree (node, id, isDel) { if (!node) { return } if (node.id === id) { if (isDel) { node.selected = false } else { node.selected = true } } let children = node.children if (children && children.length > 0) { for (let i = 0, l = children.length; i < l; i++) { this.traverseTree(children[i], id, isDel) } } } } }