之前写的,本来是以下拉列表展示,但是客户应要求以树的形式展示,百度了好久,没有找到合适的适合的树组件,最后只能自己上手了,展示效果如下:
clipboard.png

  1. 组件treeNode.vue
<style>
.treeList {
  line-height: 40px;
  font-size: 14px;
  overflow: hidden;
}
.parentTree {
  position: relative;
}
.closeli {
  position: absolute;
  right: 10px;
  top: 0;
}
.treeList .mui-icon-checkmarkempty {
  color: #3498fe;
  font-size: 30px;
}
</style>
  <template>
  <li class="treeList">
    <div :style="style">

      <div class="parentTree">
        <span @click="nodeClick(node)">{{node.entityTitle}}</span>
        <span class="mui-icon" :class="node.isChecked?'mui-icon-checkmarkempty':''"></span>
        <div v-if="node.children && node.children.length > 0" class="closeli">
          <span @click="changeStatus(node)" class="mui-icon" :class="node.close?'mui-icon-arrowdown':'mui-icon-arrowup'"></span>
          <!-- <i  @click="changeStatus(node)" v-else>折叠</i> -->
        </div>
      </div>

    </div>
    <tree-node @push="push" @remove="remove" v-show="!node.close" :level="level+2" :ref="'children'+index" :key="index" v-for="(item,index) in node.children" :node="item"></tree-node>
  </li>
</template>
  <script>
import linq from 'linq'
export default {
  data: function () {
    return {
      style: {
        paddingLeft: '',
        borderBottom: '1px solid #dedede'
      },
      vals: []
    }
  },
  props: ['node', 'ids', 'level'],
  methods: {
    // 展开状态变更
    changeStatus: function (node) {
      if (node) {
        if (node.close) {
          node.close = false
        } else {
          node.close = true
        }
      }
    },
    // 递归设置子节点的状态
    setChildrensRole: function (node, val) {
      var that = this
      if (node.children !== null && node.children.length > 0) {
        node.children.forEach(function (item, index) {
          item.isChecked = val
          if (item.children !== null) {
            that.setChildrensRole(item, val)
          }
        })
      }
    },
    nodeClick: function (node) {
      node.isChecked = !node.isChecked
      this.setChildrensRole(node, node.isChecked)
    },
    removeItem: function (val) {
      let index = linq.from(this.vals).indexOf(val)
      this.vals = this.vals.splice(index, 1, 0)
      console.log(this.vals)
    },
    push: function (val) {
      this.$emit('push', val)
    },
    remove: function (val) {
      console.log(val)
      this.$emit('remove', val)
    }
  },
  watch: {
    node: function () {
      this.$set(this.node, 'close', true)
      this.$set(this.node, 'isChecked', false)
    },
    'node.isChecked': function (val) {
      if (this.node.children && this.node.children.length === 0) {
        if (val) {
          this.$emit('push', { id: this.node.entityCode, text: this.node.entityTitle })
        } else {
          this.$emit('remove', { id: this.node.entityCode, text: this.node.entityTitle })
        }
      }
    }
  },
  created: function () {
    this.$set(this.node, 'close', true)
    this.$set(this.node, 'isChecked', false)
    if (!this.level) {
      this.level = 0
    }
    this.style.paddingLeft = (this.level * 10) + 'px'
  },
  components: {
    TreeNode: resolve => require(['./treeNode.vue'], resolve)
  }
}
</script>

2.组件tree.vue

<template>
  <div style="overflow-y:auto">
    <ul style="padding-left:5px" class="tree">
      <tree-node :level="0" @push="push" @remove="remove" :ids="ids" v-for="(item,index) in datas" :key="index" :node="item"></tree-node>
    </ul>
  </div>
</template>
<script>
import linq from 'linq'
export default {
  data () {
    return {
      ids: this.value,
      datas: [],
      labels: []
    }
  },
  props: ['nodes', 'value', 'isNeedChangData'],
  components: {
    TreeNode: resolve => require(['./treeNode.vue'], resolve)
  },
  watch: {
    nodes: function (val) {
      this.datas = this.GetData(0, val)
    }
  },
  created () {
    this.datas = this.GetData(0, this.nodes)
  },
  methods: {
    GetData: function (id, arry = this.nodes) {
      let [vm, list] = [this, []]
      var childArry = this.GetParentArry(id, arry)
      if (childArry.length > 0) {
        for (var i in childArry) {
          let test = {
            entityCode: childArry[i].entityCode,
            entityTitle: childArry[i].entityTitle,
            children: vm.GetData(childArry[i].entityId, arry)
          }
          list.push(test)
        }
      }
      return list
    },
    GetParentArry: function (id, arry) {
      var newArry = []
      for (var i in arry) {
        if (arry[i].parentId === id) {
          newArry.push(arry[i])
        }
      }
      return newArry
    },
    push: function (val) {
      if (linq.from(this.ids).indexOf(val.id) < 0) {
        this.ids.push(val.id)
        this.labels.push(val.text)
        this.$emit('input', this.ids)
        this.$emit('update:labels', this.labels)
      }
    },
    remove: function (val) {
      let index = linq.from(this.ids).indexOf(val.id)
      if (index > -1) {
        this.ids.splice(index, 1)
        this.labels.splice(index, 1)
      }
      this.$emit('input', this.ids)
      this.$emit('update:labels', this.labels)
    }
  }
}
</script>
<style v-once scoped>
ul.tree ul {
  margin-left: 0;
}
ul.tree li {
  margin: 0;
  padding: 0;
  line-height: 40px;
  color: #222;
  border-top-right-radius: 0px;
  border-top-left-radius: 0px;
}
ul.tree .licheckbox {
  float: left;
  width: 20px;
}
.positions ul li:last-child {
  border-bottom: none !important;
}
.positions {
  border-right: 1px solid;
}
</style>

3.应用到页面

<tree v-model="ids" :labels.sync="orgSelectLabels" :nodes="ownerGroups"></tree>

:labels.sync="orgSelectLabels"用于回显到前面选中的展示

clipboard.png

Logo

前往低代码交流专区

更多推荐