co-tree
v0.2.73
Published
co-tree React component
Downloads
9
Readme
co-tree
Tree ui component for react
特性
- 支持所有流行的浏览器,包括IE9及以上版本
- 用于多层次结构列表展示
- 具有展开收起选择等交互功能
使用场景
任何可以利用树形结构来展现事物层级关系的场景
Example
http://localhost:3333/
Usage
npm install co-tree
Draggable Demo
Based on the toolkit nwb
You can based on some toolkit or framework, whatever create-react-app
etc...
npm install nwb -g;
nwb new react-component test;
cd test;
npm install co-tree
import React from 'react';
import Tree from 'co-tree';
//Some very simple styles, just embed the js code
const STYLE = `
.draggable-demo {
width: 20%;
margin-left: 30px;
}
.wrapper {
background-color: #f5f7f9;
}
.node-motion {
transition: all .3s;
overflow-y: hidden;
}
`;
//Basic animation setting.
const motion = {
motionName: "node-motion",
motionAppear: false,
onAppearStart: () => ({ height: 0 }),
onAppearActive: node => ({ height: node.scrollHeight }),
onLeaveStart: node => ({ height: node.offsetHeight }),
onLeaveActive: () => ({ height: 0 })
};
//Generate Data Function
const gData = (x = 3, y = 2, z = 1, data = []) => {
//x: 每一级下的节点总数。y: 每一级节点里有y个节点、存在子节点
//y: 树的level层级(0代表一级)
const loop = (_level, _prevKey, _tns) => {
const preKey = _prevKey || '0';
const tns = _tns || data;
const children = [];
for(let i = 0; i < x; i++){
const key = `${preKey}-${i}`;
tns.push({title: `${key}`, key: `${key}-key`});
if(i < y){
children.push(key);
}
}
if(_level < 0){
return tns;
}
const __level = _level - 1;
children.forEach((key, index) => {
tns[index].children = [];
return loop(__level, key, tns[index].children);
});
return null;
};
loop(z);
return data;
};
//By the way, we can also just simply hard code data like the //following way in the component
//const gData = [
// { title: '0-0', key: '0-0' },
// { title: '0-1', key: '0-1' },
// { title: '0-2', key: '0-2', children: [{ title: '0-2-0', key: // '0-2-0' }] },
//];
const DragTree = () => {
const [_gData, setGData] = React.useState(gData);
const [autoExpandParent, setAutoExpandParent] = React.useState(true);
const [expandedKeys, setExpandedKeys] = React.useState([
"0-0-key",
"0-0-0-key",
"0-0-0-0-key"
]);
const onDragEnter = ({ expandedKeys }) => {
setExpandedKeys(expandedKeys);
};
const onDrop = info => {
const dropKey = info.node.props.eventKey;
const dragKey = info.dragNode.props.eventKey;
const dropPos = info.node.props.pos.split("-");
const dropPosition =
info.dropPosition - Number(dropPos[dropPos.length - 1]);
//Traverse the whole tree node structure
const loop = (data, key, callback) => {
data.forEach((item, index, arr) => {
if (item.key === key) {
callback(item, index, arr);
return;
}
if (item.children) {
loop(item.children, key, callback);
}
});
};
//获取原始节点数据结构
const data = [..._gData];
//被拖拽的节点对象
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (!info.dropToGap) {
// Drop on the content 释放在其他节点上
loop(data, dropKey, item => {
item.children = item.children || [];
// where to insert 示例添加到尾部,可以是随意位置
item.children.push(dragObj);
});
} else if (
(info.node.props.children || []).length > 0 && // Has children
info.node.props.expanded && // Is expanded
dropPosition === 1 // On the bottom gap
) {
loop(data, dropKey, item => {
item.children = item.children || [];
// where to insert 示例添加到尾部,可以是随意位置
item.children.unshift(dragObj);
});
} else {
// Drop on the gap 释放在节点间的gap上
let ar;
let i;
loop(data, dropKey, (_item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj);
}
}
setGData(data);
};
const onExpand = expandedKeys => {
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
};
return (
<div className="draggable-demo">
<style dangerouslySetInnerHTML={{ __html: STYLE }} />
<h2>Draggable</h2>
<p>drag a node into another node</p>
<div className='wrapper'>
<Tree
expandedKeys={expandedKeys}
onExpand={onExpand}
autoExpandParent={autoExpandParent}
draggable
onDragEnter={onDragEnter}
onDrop={onDrop}
treeData={_gData}
motion={motion}
/>
</div>
</div>
);
};
export default DragTree;
效果图
Draggable Demo使用的api解析
- expandedKeys: 用于展开指定的树节点,决定树形结构数据最初呈现(展开/收起)的样子,也可以作为其他函数的参数,用来设定节点最初的展开状态。
- onExpand: 将expandedKeys作为参数的函数,来决定哪些节点最初呈现展开状态,并且用于控制节点的开合状态。
- autoExpandParent:是否自动展开父节点。配合前两个api一起使用,来决定ui呈现时,哪些父节点自动展开。
- draggable:用于决定组件的节点是否能被拖拽。
- onDragEnter:当被拖拽的节点进入另外的父节点时,该节点自动展开。
- onDrop: 处理被拖拽节点释放位置的具体情况(放置于
gap
之间节点变换位置,放置于其他节点上,变成该节点的子节点等)。 - treeData:决定组件的数据结构,具体收到怎样的数据,最终节点便会有怎样的ui呈现。
- motion:处理运用于组件的简单动画设置。
组件其他部分常用api解析
- disabled: 禁用某节点,主要用于禁止节点的拖拽、选中等功能,并不影响父节点的展开/收起以及图标的更换。
- icon:用于自定义图标,可直接用在数据中,在json数据中添加icon的选项信息,也可以设置更换图标的函数,配合switcherIcon一起使用。
- multiple:通过点击可以选中多个节点(配合selectable一起使用)。
- selectable:是否可以选中节点,默认值为true。
- title:用于设置节点标题信息的API,可直接放置于json信息中,也可具体设置。
- showIcon: 是否显示节点图标,默认值为true,我们也可以将其手动设置成false;
API
Tree Props
| 参数 | 描述 | 类型 | 默认值 |
| ------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | --------- |
| autoExpandParent | 是否自动展开父节点 | bool | false |
| className | 根 dom 节点的附加 css 类 | string | ‘’ |
| defaultExpandedKey | 默认展开指定的树节点 | string[] | [] |
| defaultExpandAll | 默认展开所有树节点 | bool | false |
| defaultExpandParent | 默认展开父节点 | bool | true |
| defaultSelectedKeys | 默认选中的树节点 | string[] | [] |
| disabled | 将树禁用 | bool | false |
| draggable | 设置节点可拖拽(IE > 8 & Safari > 5.1) | bool | false |
| expandedKeys | (受控)展开指定的树节点 | string[] | - |
| filterTreeNode | 按需筛选树节点(高亮), 返回true | function (node) | - |
| icon | 自定义图标。可接受组件, props为当前节点props | element/Function(props) | - |
| loadedKeys | (受控)已加载的节点,需要配合loadData
使用 | string[] | - |
| loadData | 异步加载数据,返回一个promise | function(node) | - |
| multiple | 支持点选多个节点(节点本身) | bool | false |
| prefixCls | 类名前缀 | string | 'co-tree' |
| selectable | 是否可选中 | bool | true |
| selectedKeys | (受控)设置选中的树节点(若设置了defaultSelectedKeys便不会生效) | string[] | [] |
| showIcon | 是否显示图标 | bool | true |
| showLine | 是否显示连接线 | bool | false |
| treeData | treeNodes 数据,如果设置则不需要手动构造 TreeNode 节点(key 在整个树范围内唯一) | array<{key, title,children,[disabled,selectable]}> | - |
| onExpand | 展开/收起节点时触发 | function(expandedKeys, {expanded: bool, node, nativeEvent}) | - |
| onDragEnd | dragEnd 触发时调用 | function({event, node}) | - |
| onDragEnter | dragEnter触发时调用 | function({event, node, expandedKeys}) | - |
| onDragLeave | dragLeave触发时调用 | function({event, node}) | - |
| onDragStart | dragStart触发时调用 | function({event, node}) | - |
| onDrop | drop触发时调用 | function({event, node, dragNode, dragNodesKeys}) | - |
| onLoad | 节点加载完毕时触发, 如果设置了loadedKeys
, 便必需设置onLoad
来避免无限循环 | function(loadedKeys, {event, node}) | - |
| onMouseEnter | 当光标进入树节点时响应 | function({event, node}) | - |
| onMouseLeave | 当光标离开树节点时响应 | function({event, node}) | - |
| onRightClick | 响应右键点击显示自定义的内容菜单 | function({event, node}) | - |
| onSelect | 点击树节点时触发 | function(selectedKeys, e: {selected: bool, selectedNodes, node, event, nativeEvent}) | - |
| switcherIcon | 切换具体图标 | ReactNode / (props: TreeNodeAttribute) => ReactNode | - |
TreeNode Props
note: 如果你有很多个树节点,若有超过一千个节点,
建议将父节点设置成默认
收起
,这样整体树结构展示便会非常有效迅速,因为藏起来的子节点是不会插入dom中的
| 属性 | 描述 | 类型 | 默认值 | | ------------ | ------------------------------------------------------------ | --------------------------------------------------- | ------------------- | | className | 树节点的附加类 | string | '' | | style | 为树节点设置样式 | object | - | | disabled | 禁止响应 | bool | false | | title | 标题 | string/element/((data:DataNode) => React.ReactNode) | '---' | | key | 被树的 (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys 属性所用。注意:整个树范围内的所有节点的 key 值不能重复! | string | treeNode's position | | isLeaf | 设置为叶子节点 | bool | false | | icon | 自定义图标。可接收组件,props 为当前节点 props | element/Function(props) | - | | switcherIcon | 切换具体的图标 | ReactNode /(props: TreeNodeAttribute) => ReactNode | - |
Development
npm install
npm start
License
co-tree is released under the MIT license