iView 用renderContent自定义树组件

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)
        }
      }
    }
  }
}
原文地址:https://www.cnblogs.com/ToBeBest/p/9606213.html