# Tree 树形控件
用清晰的层级结构展示信息,可展开或折叠。
# 基础用法
基础的树形结构展示。
  一级 1
   一级 2
   一级 3
 <j-tree :list="data" :props="defaultProps" @click="handleNodeClick"></j-tree>
<script>
  export default {
    data() {
      return {
        data: [{
          label: '一级 1',
          children: [{
            label: '二级 1-1',
            children: [{
              label: '三级 1-1-1'
            }]
          }]
        }, {
          label: '一级 2',
          children: [{
            label: '二级 2-1',
            children: [{
              label: '三级 2-1-1'
            }]
          }, {
            label: '二级 2-2',
            children: [{
              label: '三级 2-2-1'
            }]
          }]
        }, {
          label: '一级 3',
          children: [{
            label: '二级 3-1',
            children: [{
              label: '三级 3-1-1'
            }]
          }, {
            label: '二级 3-2',
            children: [{
              label: '三级 3-2-1'
            }]
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    },
    methods: {
      handleNodeClick(data) {
        console.log(data);
      }
    }
  };
</script>
 显示代码 复制代码 复制代码
# 可选择
适用于需要选择层级时使用。
  a
   b
 <j-tree
   tKey="sku"
  :list="data"
  :props="props"
  checkbox
  @check="handleCheckChange">
</j-tree>
<script>
  export default {
    data() {
      return {
        data: [
        { size: 'a', sku: '1',
          childList: [{ size: 'a1', sku: '1-1',
            childList: [{ size: 'a11', sku: '1-1-1',
              childList: [{ size: 'a111', sku: '1-1-1-1' }, { size: 'a112', sku: '1-1-1-2' }]
            }, { size: 'a12', sku: '1-1-2' }] }]
        },
        { size: 'b', sku: '2',
          childList: [{ size: 'b1', sku: '2-1',
            childList: [{ size: 'b11', sku: '2-1-1' }] }]
        }
      ],
        props: {
          label: 'size',
          children: 'childList'
        },
        count: 1
      };
    },
    methods: {
      handleCheckChange( checked, data,nodeData) {
        console.log( checked, data,nodeData);
      }
    }
  };
</script>
 显示代码 复制代码 复制代码
# 默认展开和默认选中
可将 Tree 的某些节点设置为默认展开或默认选中
  一级 1
   一级 2
   二级 2-1
   二级 2-2
   一级 3
 1.分别通过default-opened和default-checked设置默认展开和默认选中的节点。需要注意的是,此时必须设置t-key,其值为节点数据中的一个字段名,该字段在整棵树中是唯一的;2.也可设置数据中对应的$checked和$opened来达到默认选中,默认展开的效果;
<j-tree
  :list="data"
  checkbox
  t-key="id"
  :default-opened="[3]"
  :default-checked="[5]"
  :props="defaultProps">
</j-tree>
<script>
  export default {
    data() {
      return {
        data: [{
          id: 1,
          label: '一级 1',
          $checked:true,
          children: [{
            id: 4,
            label: '二级 1-1',
            children: [{
              id: 9,
              label: '三级 1-1-1'
            }, {
              id: 10,
              label: '三级 1-1-2'
            }]
          }]
        }, {
          id: 2,
          label: '一级 2',
          $opened:true,
          children: [{
            id: 5,
            label: '二级 2-1'
          }, {
            id: 6,
            label: '二级 2-2'
          }]
        }, {
          id: 3,
          label: '一级 3',
          children: [{
            id: 7,
            label: '二级 3-1'
          }, {
            id: 8,
            label: '二级 3-2'
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    }
  };
</script>
 显示代码 复制代码 复制代码
# 展开/关闭所有选中节点和展开/关闭所有节点
可通过 tree 的指定方法达成所需效果
  一级 1
   一级 2
   一级 3
 <j-tree
  :list="data"
  ref="tree1"
  checkbox
  t-key="id"
  :props="defaultProps">
</j-tree>
<j-button class="small" @click="$refs.tree1.openChecked()">展开选中节点</j-button>
<j-button class="small" @click="$refs.tree1.closeUnchecked()">折叠未选中添加节点</j-button>
<j-button class="small" @click="$refs.tree1.openAll()">展开所有节点</j-button>
<j-button class="small" @click="$refs.tree1.closeAll()">折叠所有节点</j-button>
<script>
  export default {
    data() {
      return {
        data: [{
          id: 1,
          label: '一级 1',
          children: [{
            id: 4,
            label: '二级 1-1',
            children: [{
              id: 9,
              label: '三级 1-1-1'
            }, {
              id: 10,
              label: '三级 1-1-2',
              children: [{
                $checked:true,
                id: 11,
                label: '三级 1-1-1'
              }, {
                id: 12,
                label: '三级 1-1-2'
              }]
            }]
          }]
        }, {
          id: 2,
          label: '一级 2',
          children: [{
            id: 5,
            label: '二级 2-1'
          }, {
            id: 6,
            label: '二级 2-2'
          }]
        }, {
          id: 3,
          label: '一级 3',
          children: [{
            id: 7,
            label: '二级 3-1'
          }, {
            id: 8,
            label: '二级 3-2'
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    }
  };
</script>
 显示代码 复制代码 复制代码
# 禁用状态
可将 Tree 的某些节点设置为禁用状态
  一级 2
 通过$disabled设置禁用状态。
<j-tree
  :list="data"
  checkbox
  t-key="id"
  :default-opened="[2, 3]"
  :default-checked="[5]">
</j-tree>
<script>
  export default {
    data() {
      return {
        data: [{
          id: 1,
          label: '一级 2',
          children: [{
            id: 3,
            label: '二级 2-1',
            children: [{
              id: 4,
              label: '三级 3-1-1'
            }, {
              id: 5,
              label: '三级 3-1-2',
              $disabled: true
            }]
          }, {
            id: 2,
            label: '二级 2-2',
            $disabled: true,
            children: [{
              id: 6,
              label: '三级 3-2-1'
            }, {
              id: 7,
              label: '三级 3-2-2',
              $disabled: true
            }]
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    }
  };
</script>
 显示代码 复制代码 复制代码
# 树节点的选择
本例展示如何获取和设置选中节点。获取和设置各有两种方式:通过 key。如果需要通过 key 来获取或设置,则必须设置t-key。
如果需要默认选中样式,可以使用setCurrentKey,前提是必须设置highlight-current属性
<j-tree
  :list="data"
  checkbox
  opened-all
  t-key="id"
  ref="tree"
  highlight-current
  :props="defaultProps">
</j-tree>
<div class="buttons">
  <j-button @click="getChecked">获取选中数据</j-button>
  <j-button @click="setChecked">通过 key 设置</j-button>
  <j-button @click="resetChecked">清空</j-button>
</div>
<script>
  export default {
    mounted(){
      this.$refs.tree.setCurrentKey(1);
    },
    methods: {
      getChecked() {
        console.log(this.$refs.tree.getChecked());
      },
      setChecked() {
        this.$refs.tree.setChecked([3]);
      },
      resetChecked() {
        this.$refs.tree.setChecked([]);
      }
    },
    data() {
      return {
        data: [{
          id: 1,
          label: '一级 1',
          children: [{
            id: 4,
            label: '二级 1-1',
            children: [{
              id: 9,
              label: '三级 1-1-1'
            }, {
              id: 10,
              label: '三级 1-1-2'
            }]
          }]
        }, {
          id: 2,
          label: '一级 2',
          children: [{
            id: 5,
            label: '二级 2-1'
          }, {
            id: 6,
            label: '二级 2-2'
          }]
        }, {
          id: 3,
          label: '一级 3',
          children: [{
            id: 7,
            label: '二级 3-1'
          }, {
            id: 8,
            label: '二级 3-2'
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    }
  };
</script>
 显示代码 复制代码 复制代码
# 自定义节点内容
节点的内容支持自定义,可以在节点区添加按钮或图标等内容
  一级 1  
   二级 1-1  
   三级 1-1-1  
   三级 1-1-2  
   一级 2  
   二级 2-1  
   二级 2-2  
   一级 3  
   二级 3-1  
   二级 3-2  
 可以通过两种方法进行树节点内容的自定义:render-content和 scoped slot。使用render-content指定渲染函数,该函数返回需要的节点区内容即可。渲染函数的用法请参考 Vue 文档。使用 scoped slot 会传入两个参数node和data,分别表示当前节点的 Node 对象和当前节点的数据。注意:由于 jsfiddle 不支持 JSX 语法,所以render-content示例在 jsfiddle 中无法运行。但是在实际的项目中,只要正确地配置了相关依赖,就可以正常运行。
<j-tree
  ref="treeZdy"
  :list="data"
  t-key="id"
  opened-all
  @click="handleNodeClick">
  <span class="custom-tree-node" slot-scope="{ vnode, data }">
    <span>{{data.label}}</span>
    <span style="margin-left:20px;">
        <i class="j-icon icon-add-select" @click.stop="addChild(data)"></i>
        <i class="j-icon icon-sami-select" @click.stop="deleteChild(data,vnode)"></i>
    </span>
  </span>
</j-tree>
<j-button @click="addActiveChild">添加子节点</j-button>
<script>
  var id=1000;
  export default {
    data() {
      const data = [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1',
          children: [{
            id: 9,
            label: '三级 1-1-1',
            children:[]
          }, {
            id: 10,
            label: '三级 1-1-2',
            children:[]
          }]
        }]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1',
          children:[]
        }, {
          id: 6,
          label: '二级 2-2',
          children:[]
        }]
      }, {
        id: 3,
        label: '一级 3',
        children: [{
          id: 7,
          label: '二级 3-1',
          children:[]
        }, {
          id: 8,
          label: '二级 3-2',
          children:[]
        }]
      }];
      return {
        data: JSON.parse(JSON.stringify(data)),
      }
    },
    methods: {
      handleNodeClick(data,vnode){
        console.log(data,vnode);
      },
      addChild(data){
        const newChild = {id:id++,label: 'testtest'+id, children: [] };
         if (!data.children) {
          this.$set(data, 'children', []);
        }
        data.children.push(newChild);
      },
      deleteChild(data,vnode){
        const parent = vnode.componentInstance.parent;
        if(parent){
          const index = parent.children.findIndex(d => d.id === data.id);
          parent.children.splice(index, 1);
        }else{
          const index = this.data.findIndex(d => d.id === data.id);
          this.data.splice(index, 1);
        }
      },
      addActiveChild(){
        // 当前子节点添加,若无选中节点则添加到根节点
        this.$refs.treeZdy.appendActivedTree([{id:id++,label: 'testtest'+id, children: [] }])
        // 当前子节点指定位置添加
        //this.$refs.treeZdy.appendActivedTree([{id:id++,label: 'testtest'+id, children: [] }],1)
        // 根节点添加
        // this.$refs.treeZdy.appendActivedTree([{id:id++,label: 'testtest'+id, children: [] }],1,true)
      }
    }
  };
</script>
<style>
  .custom-tree-node{
    width:50%;
    display:flex;
  }
  .icon-add-select{
    color:#257fea;
  }
  .icon-sami-select{
    color:red;
  }
</style>
 显示代码 复制代码 复制代码
# 手风琴模式
对于同一级的节点,每次只能展开一个
  一级 1
   一级 2
   一级 3
 <j-tree
  :list="data"
  :props="defaultProps"
  accordion
  @click="handleNodeClick">
</j-tree>
<script>
  export default {
    data() {
      return {
        data: [{
          label: '一级 1',
          children: [{
            label: '二级 1-1',
            children: [{
              label: '三级 1-1-1'
            }]
          }]
        }, {
          label: '一级 2',
          children: [{
            label: '二级 2-1',
            children: [{
              label: '三级 2-1-1'
            }]
          }, {
            label: '二级 2-2',
            children: [{
              label: '三级 2-2-1'
            }]
          }]
        }, {
          label: '一级 3',
          children: [{
            label: '二级 3-1',
            children: [{
              label: '三级 3-1-1'
            }]
          }, {
            label: '二级 3-2',
            children: [{
              label: '三级 3-2-1'
            }]
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    },
    methods: {
      handleNodeClick(data) {
        console.log(data);
      }
    }
  };
</script>
 显示代码 复制代码 复制代码
# Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 
|---|---|---|---|---|
| data | 展示数据 | array | — | — | 
| empty-text | 内容为空的时候展示的文本 | String | — | — | 
| t-key | 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的 | String | — | — | 
| props | 配置选项,具体看下表 | object | — | — | 
| render-after-opened | 是否在第一次展开某个树节点后才渲染其子节点 | boolean | — | true | 
| opened-all | 是否默认展开所有节点 | boolean | — | false | 
| default-opened | 默认展开的节点的 key 的数组 | array | — | — | 
| checkbox | 节点是否可被选择 | boolean | — | false | 
| default-checked | 默认勾选的节点的 key 的数组 | array | — | — | 
| accordion | 是否每次只打开一个同级树节点展开 | boolean | — | false | 
| check-level | 选择层级联动 | boolean | — | false | 
# props
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 
|---|---|---|---|---|
| label | 指定节点标签为节点对象的某个属性值 | string, function(data, node) | — | — | 
| children | 指定子树为节点对象的某个属性值 | string | — | — | 
| disabled | 指定节点选择框是否禁用为节点对象的某个属性值 | boolean, function(data, node) | — | — | 
# 方法
Tree 内部使用了 Node 类型的对象来包装用户传入的数据,用来保存目前节点的状态。
Tree 拥有如下方法:
| 方法名 | 说明 | 参数 | 
|---|---|---|
| getChecked | 若节点可被选择(即 checkbox 为 true),则返回目前被选中的节点所组成的数组,使用此方法必须设置 t-key 属性 |  — | 
| setChecked | 设置勾选的节点, 使用此方法必须设置 t-key 属性 | 勾选节点的 key 的数组 | 
| openChecked | 展开所有复选框选中的节点 | — | 
| closeUnchecked | 折叠所有复选框未选中的节点 | — | 
| openAll | 展开所有节点 | — | 
| closeAll | 折叠所有节点 | — | 
| setCurrentKey | 默认选中节点样式 | — | 
# Events
| 事件名称 | 说明 | 回调参数 | 
|---|---|---|
| click | 节点被点击时的回调 | 共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node。 | 
| check | 当复选框被点击的时候触发 | 共三个参数,依次为:树目前的选中状态对象、传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node | 
| item-dblclick | 没有子集的节点被双击时的回调 | 共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node。 | 
# Scoped Slot
| name | 说明 | 
|---|---|
| — | 自定义树节点的内容,参数为 { vnode, data } |