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) } } } } }