vue封装树形组件tree

 

       我们项目中有很多需要用到树形组件的,以前写jq的时候用ztree,现在写vue,感觉找不到像ztree一样好用的树形组件,又不想在vue总用jq,所以打算自己封装一个tree组件,花了两个时间才搞完一些基本功能,不过已经可以正常使用了,效果如下:

vue封装树形组件tree_第1张图片

图标的问题大家可以自行用ztree的样式去修改

加上上周的折叠式菜单,gitHub网址:https://github.com/421119407/vue-kwt-cly

做这个树形菜单是采用了递归组件的思路,因为事件只能传递一层,所以需要每一层子组件触发上一层父组件的事件。

然后通过Vue.set(对象,属性,值)的方式动态给对象添加属性

模板:

 父组件传递属性:

props: {
      iconStyle: {
        type: String,
        default: icon.iconStyle.METRO
      },
      depth: {
        type: Number,
        default: 1
      },
      opinions: {
        type: Object,
        default: () => null
      },
      datas: {
        type: Array,
        default: () => []
      },
      parent: {
        type: Object,
        default: () => null
      },
      halfCheck: {
        type: Boolean,
        default: true
      },
      multiple: {
        type: Boolean,
        default: true
      },
      checkModel: {
        type: Boolean,
        default: true
      },
      draggable: {
        type: Boolean,
        default: false
      },
      drapAfterExpand: {
        type: Boolean,
        default: false
      },
      showCheck: {
        type: Boolean,
        default: false
      },
      isAddOrEdit: {
        type: Boolean,
        default: false
      },
      scoped: {
        type: Boolean,
        default: false
      },
      tpl: Function
    }

 datas:  父组件向子组件传递数据,也就是我们的树形信息。包括节点id,节点父id。。。

parent: 当前节点的父节点

opinions:封装了节点对应信息,主要用来转换后台传来的数据转成树形菜单适用的数据,我们后台传来的数据一般没有父子关系,需要通过特殊处理,转换成

{

   id:1

  children:【{

      id:11

}】

}

halfCheck:半选模式

checkModel:是否显示复选框

scoped:是否父子关联

multiple:是否可复选

tpl:这返回的是一个函数,可自定义标题模板

 

在父组件中:

可通过自定义事件绑定on-click,来自定义点击回调事件

 

数据处理片段:

initDatas() {
        let dataArray = []
        let pidArray = []
         //找出根节点,放入数组中
        for (let key of this.datas) {
          pidArray.push(key[this.opinions.id])   //遍历数据,把id存储在数据中
        }
        for (let key of this.datas) {
          if (pidArray.indexOf(key[this.opinions.pid]) === -1) {  //判断pid是否存在数组中,不存在的那个节点,便是根节点
            dataArray.push({
              id: key[this.opinions.id],
              name: key[this.opinions.name],
              checked: key.checked,
              visible: key.visible
            })
          }
        }
        return this.initArrayDatas(dataArray)
      },
      initArrayDatas(dataArray) {
        for (let key of dataArray) {
          let childDatas = []
          for (let k of this.datas) {      //遍历,通过pid===id建立父子关系
            if (key.id === k[this.opinions.pid]) {  
              childDatas.push({
                id: k[this.opinions.id],
                name: k[this.opinions.name],
                pid: k[this.opinions.pid],
                checked: k.checked,
                visible: k.visible
              })
            }
          }
          key.children = childDatas   //  添加进children
          if (childDatas.length > 0) {
            this.initArrayDatas(childDatas)
          }
        }
        return dataArray
      },

 

筛选节点:

getNodes(opt, data, isOriginal) {  
        data = data || this.datas
        let res = []
        for (const node of data) {
          for (const [key, value] of Object.entries(opt)) {
            if (node[key === value]) {
              if (isOriginal) {
                res.push(node)
              } else {
                let n = Object.assign({}, node)
                delete n['children']
                delete n['parent']
                res.push(n)
              }
            }
          }
          if (node.children && node.children.length) {
            res = res.concat(this.getNodes(opt, node.children, isOriginal))
          }
        }
        return res
      },
      getSelectNodes(isOriginal) {
        return this.getNodes({ select: true }, this.data, isOriginal)
      },
      getCheckedNodes(isOriginal) {
        return this.getNodes({ checked: true }, this.data, isOriginal)
      },

opt参数封装筛选条件,如{checked:true,select:true},然后遍历数据找到符合条件的节点并添加到数组中返回

getSelectNodes和getCheckedNodes可用于点击回调中获取选中节点的值

 

到了这里,我们的属性组件基本就封装完成了,当然了,后期我会逐步完善其他功能。

你可能感兴趣的:(vue封装树形组件tree)