Ant Design of Vue的树形控件Tree的使用及说明
作者:飞鱼爱吃米
基本使用
配置项
replaceFields
数据渲染属性依赖3个字段:
title
key
children
没有其他可携带的用户数据
对接实际后台返回的数据,很多时候不是直接的title、key可以让我们直接渲染,这个时候replaceFields 就派上了用场。
举栗:
:replaceFields="{ title: 'buildingName', key: 'buildingId' }"
这里的buildingName作为title渲染,buildingId作为key
需要注意的是:设置为key的字段,一定要确保它的唯一性哦!!!
treeData
树节点渲染的数据
两种方法设置:
- 1、手动构造
const treeData = [ { title: '0-0', key: '0-0', children: [ { title: '0-0-0', key: '0-0-0', children: [ { title: '0-0-0-0', key: '0-0-0-0' }, { title: '0-0-0-1', key: '0-0-0-1' }, { title: '0-0-0-2', key: '0-0-0-2' }, ], }, { title: '0-0-1', key: '0-0-1', children: [ { title: '0-0-1-0', key: '0-0-1-0' }, { title: '0-0-1-1', key: '0-0-1-1' }, { title: '0-0-1-2', key: '0-0-1-2' }, ], }, ], }, ];
- 2、返回的接口数据构造
在这里呢,同样有两种情况,子树的数据
- ①同一个接口获取
这里建议使用控件里面的异步加载loadData,详细介绍请移步配置项介绍处。
实现方式是:进入页面即调用getTree的方法,拿到主树的数据,其后每展开一层就会调用它的onLoadData方法,构造子树数据作为children放在主树对应的节点下。
举栗:
:load-data="onLoadData"
// 获取部门树 getTree() { classTree() .then((res) => { if (res.data.code == '200') { let data = res.data.result.treeobject; if (!this.defaultSelectedkeys.length) { this.defaultSelectedkeys.push(data.buildingId); } let obj = { title: data.buildingName, key: data.buildingId, }; this.treeData.push(obj); } else { this.loading = false; } }) .catch(() => { this.loading = false; }); }, //异步加载树形数据 onLoadData(treeNode) { return new Promise((resolve) => { if (treeNode.dataRef.children) { resolve(); return; } const { current, pageSize } = this.pagination; let child = []; childList(current, pageSize, treeNode.dataRef.key).then((res) => { if (res.data.code == '200') { res.data.result.listobject.forEach((item, index) => { let obj = {}; obj = { title: item.buildingName, key: item.buildingId, }; child.push(obj); }); treeNode.dataRef.children = child; this.treeData = [...this.treeData]; resolve(); } }); }); },
- ②多个接口获取
这里需要配合select事件完成,详细介绍请移步配置项介绍处。
需要注意的是:不同于从同一个接口获取子树数据:数据在一张表中,key的值可以确保唯一性,多个接口获取key的唯一性需要保证,我这边是和后台约定了一个字段作为标识:它由本身id加上前缀字母组成,这样我们拿到的时候把它做一下处理既能知道它具体的哪个层级的数据,还能根据它的id继续查找子树。
实现方式是:初始化渲染 getTree方法,加载主树。选中的树节点会调用_select方法,查到下一级的子树数据并添加至对应节点处。每次进入_select方法都会先判断具体是哪一层的子树,然后再拿着id去查找下级作为子树数据。
// 树形结构选中项 _select(e, node) { if (!e.length) { return; } //第二层 if (e[0].includes('B')) { //保存id,方便找到需要添加子树的位置 this.a = e[0].substring(1); let data1 = { curPage: current, pageSize: 1000, orderDirection, orderFieldName, buildingId: e[0].substring(1), }; floorList(data1).then((res) => { if (res.data.code == '200') { let children1 = []; res.data.result.pageobject.content.forEach((item1, index1) => { //构造数据时注意整棵树的title、key一旦被替换就只能渲染替换后字段的数据 let obj = { buildingName: item1.floorName, buildingId: item1.floorCode, }; this.$set(children1, item1.floorId, obj); }); this.$set(this.treeData2[this.a], 'children', children1); } }); //第三层 } else if (e[0].includes('f')) { this.b = e[0].substring(1); let data2 = { curPage: current, pageSize: 1000, orderDirection, orderFieldName, floorId: e[0].substring(1), }; roomList(data2).then((res) => { if (res.data.code == '200') { let children2 = []; res.data.result.pageobject.content.forEach((item2, index2) => { let obj = { buildingName: item2.roomName, buildingId: item2.roomCode, }; children2.push(obj); }); this.$set(this.treeData2[this.a].children[this.b], 'children', children2); } }); //第四层(最后一层的叶子节点,整棵树构造完成,我们根据它的id调取展示数据,用表格展示) } else if (e[0].includes('r')) { let data3 = { curPage: current, pageSize: 1000, orderDirection, orderFieldName, roomId: e[0].substring(1), }; bedList(data3).then((res) => { if (res.data.code =='200') { this.tableData = res.data.result.pageobject.content; } }); } },
defaultSelectedKeys
默认选中的树节点
是一个数组对象,多在select方法中被赋值
在获取某个树节点的数据时很好用
loadData
异步加载数据
树本身的结构比较深,在构造数据时困难之处就在于获取的数据不知道要作为哪层的子树数据。
loadData
方法就帮助我们解决了这个难题,它的回调里面有node,当前的节点。treeNode.data
Ref包含当前节点的title、key、children,这样我们在loadData里面获取子树数据后就不用苦恼该给哪层的父节点添加了。
isLeaf
- 叶子节点
在数据处理时,我们可以根据返回的数据中的某个字段,来设置它是否为叶子节点。
设置叶子节点是为了更好的展示节点前的展开标识。
showLine
- 连接线
默认情况下,树节点的展开和关闭是由下三角和右三角作为展示的
举栗:
如果我们不想使用默认的标识,就可以配置show-line属性
举栗:
由+、-标识展开收缩
如果不喜欢默认的图标,可以自定义展开收缩图标
举栗:
<a-icon slot="switcherIcon" type="home" theme="filled" />
比较好玩的就是你设置的图标在收缩状态的朝向左边的,展开后位置归正
showIcon
举栗:
<a-icon slot="smile" type="smile-o" />
treeData = [ { title: 'parent 1', key: '0-0', slots: { icon: 'smile', }, children: [ { title: 'leaf', key: '0-0-0', slots: { icon: 'meh' } }, { title: 'leaf', key: '0-0-1', scopedSlots: { icon: 'custom' } }, ], }, ];
事件
expand
在默认展开某些指定节点时适用
举栗:添加这两项配置:expanded-keys="expandedKeys" @expand="onExpand"
// 展开树形结构 onExpand(expandedKeys) { //expandedKeys是被展开节点的key组成的数组 let arr = expandedKeys.splice(-1); this.expandedKeys = arr; },
rightClick
响应右键的点击操作,回调里面提供事件对象event、节点node
select
响应点击树节点操作,回调提供选中的树节点的key、节点node
进阶使用
目录树
<template> <a-directory-tree multiple default-expand-all @select="onSelect" @expand="onExpand"> <a-tree-node key="0-0" title="parent 0"> <a-tree-node key="0-0-0" title="leaf 0-0" is-leaf /> <a-tree-node key="0-0-1" title="leaf 0-1" is-leaf /> </a-tree-node> <a-tree-node key="0-1" title="parent 1"> <a-tree-node key="0-1-0" title="leaf 1-0" is-leaf /> <a-tree-node key="0-1-1" title="leaf 1-1" is-leaf /> </a-tree-node> </a-directory-tree> </template> <script> export default { methods: { onSelect(keys, event) { console.log('Trigger Select', keys, event); }, onExpand() { console.log('Trigger Expand'); }, }, }; </script>
右键菜单树
<a-tree show-line class="draggable-tree" :load-data="onLoadData" :tree-data="treeData" :defaultSelectedKeys="defaultSelectedkeys" @select="_select"> //把key作为treeKey <template #title="{ key: treeKey, title }"> <a-dropdown :trigger="['contextmenu']"> <span>{{ title }}</span> <template #overlay> <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey)"> <a-menu-item key="1">添加</a-menu-item> <a-menu-item key="2">修改</a-menu-item> <a-menu-item key="3">删除</a-menu-item> </a-menu> </template> </a-dropdown> </template> </a-tree> //右键菜单 onContextMenuClick(treeKey, menuKey) { //treeKey是被唤起右键菜单的树节点的key,menuKey被点击的右键菜单的key this.treeKey = treeKey; this.menuKey = menuKey; if (menuKey == '1') { this.title = '添加组织'; } else if (menuKey == '2') { this.title = '修改组织'; } else { this.title = '删除组织'; } },
可搜索的树
最近没有使用到,所以对这个了解不是很全面,详细情况请访问官网介绍,挺详细的—>可搜索树
高阶使用
添加树节点
配合右键菜单使用,右键菜单项:添加,点击添加节点数据后,树形的数据可以直接变化。
在添加树节点的时候会遇到一个问题就是,添加好的数据作为哪个节点的子树。
在树形控件的方法里面,能用在这里可以提供node的是rightClick、select。
我们在右击事件里面把节点存储起来,这样我们做右键菜单的操作的时候就能确定到底是哪个节点了。
举栗:
// 响应右键点击 onrightClick({ node }) { this.nodeobj = node; },
目前有关树形的操作涉及到的方面就上面这些了。
总而言之
操作树,就是对对应树节点node做处理,知道node和key,就能完成大部分的树操作了。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。