Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/devui-vue/devui/tree/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { App } from 'vue';
import Tree from './src/tree';
import NewTree from './src/new-tree';

export * from './src/tree-types';

export { Tree };
export { Tree, NewTree };

export default {
title: 'Tree 树',
category: '数据展示',
status: '20%',
install(app: App): void {
app.component(Tree.name, Tree);
app.component(NewTree.name, NewTree);
}
};
27 changes: 17 additions & 10 deletions packages/devui-vue/devui/tree/src/components/tree-node-toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineComponent, PropType, toRefs } from 'vue';
import { ITreeNode } from '../core/tree-factory-types';
import { defineComponent, inject, PropType, toRefs } from 'vue';
import { USE_TREE_TOKEN } from '../const';
import { ITreeNode } from '../core/use-tree-types';
import { IconClose } from './icon-close';
import { IconOpen } from './icon-open';

Expand All @@ -12,17 +13,23 @@ export default defineComponent({
},
setup(props) {
const { data } = toRefs(props);
const { toggleNode } = inject(USE_TREE_TOKEN);

return () => {
return (
<span class="devui-tree-node__folder">
{data.value.isLeaf ? (
<span class="devui-tree-node__indent" />
) : data.value.expanded ? (
<IconOpen class="mr-xs" />
) : (
<IconClose class="mr-xs" />
)}
<span
class={['devui-tree-node__folder', data.value?.disableToggle && 'toggle-disabled']}
onClick={(event: MouseEvent) => {
event.stopPropagation();
toggleNode(data.value);
}}>
{
data.value.isLeaf
? <span class="devui-tree-node__indent" />
: data.value.expanded
? <IconOpen class="mr-xs" />
: <IconClose class="mr-xs" />
}
</span>
);
};
Expand Down
26 changes: 18 additions & 8 deletions packages/devui-vue/devui/tree/src/components/tree-node.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
import { defineComponent, PropType, ref, toRefs } from 'vue';
import { ITreeNode } from '../core/tree-factory-types';
import { defineComponent, inject, PropType, toRefs } from 'vue';
import { USE_TREE_TOKEN } from '../const';
import { IInnerTreeNode } from '../core/use-tree-types';
import DTreeNodeToggle from './tree-node-toggle';
import { Checkbox } from '../../../checkbox';

export default defineComponent({
name: 'DTreeNode',
props: {
data: {
type: Object as PropType<ITreeNode>,
type: Object as PropType<IInnerTreeNode>,
},
},
setup(props) {
const { data } = toRefs(props);
const { selectNode, toggleCheckNode } = inject(USE_TREE_TOKEN);

return () => {
return (
<div
class={['devui-tree-node', data.value.expanded && 'devui-tree-node__open']}
style={{ paddingLeft: `${24 * (data.value.level - 1)}px` }}>
<div class="devui-tree-node__content">
class={['devui-tree-node', data.value?.expanded && 'devui-tree-node__open']}
style={{ paddingLeft: `${24 * (data.value?.level - 1)}px` }}>
<div class={['devui-tree-node__content', data.value?.selected && 'active']} onClick={() => {
selectNode(data.value);
}}>
<DTreeNodeToggle data={data.value} />
<div class="devui-tree-node__content--value-wrapper">
<DTreeNodeToggle data={data.value} />
<span class="devui-tree-node__title">{data.value.label}</span>
{ <Checkbox disabled={data.value?.disableCheck} key={data.value?.id} modelValue={data.value?.checked} onUpdate:modelValue={() => {
toggleCheckNode(data.value);
}} onClick={(event: MouseEvent) => {
event.stopPropagation();
}} /> }
<span class={['devui-tree-node__title', data.value?.disableSelect && 'select-disabled']}>{data.value?.label}</span>
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/devui-vue/devui/tree/src/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const USE_TREE_TOKEN = 'use-tree-token';
81 changes: 61 additions & 20 deletions packages/devui-vue/devui/tree/src/core/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# Tree Factory
# useTree

Tree 组件最核心的部分,是 UI 无关的,用于树形结构的处理。

- 获取 / 设置整棵树
- 获取子节点
- 搜索节点
- 插入 / 移除 / 编辑节点
- 点选 / 勾选 / 展开收起节点
- 点选 / 勾选 / 展开收起节点功能的禁用
- 点击选择 / 勾选 / 展开收起节点
- 点击选择 / 勾选 / 展开收起节点功能的禁用

## 快速开始

```ts
const treeData = [
const data = [
{
label: 'Parent node 1',
children: [
Expand All @@ -22,30 +22,71 @@ const treeData = [
{ label: 'Leaf node 2' }
];

const treeFactory = new TreeFactory(treeData);
treeFactory.getTree();
const { getExpendedTree } = useTree(data, [useSelect, useCheck]);
```

## API

`useTree`支持插件化,每个功能都是一个插件,内置`useCore`/`useToggle`两个插件,其他插件可以手动引入,未引入的插件代码不会执行,也不会包含在构建产物里。

插件:
- useCore 核心插件(内置)
- useToggle 展开收起(内置)
- useSelect 点击选择
- useCheck 勾选
- useDisable 禁用
- useOperate 节点操作

### useCore

| 名称 | 描述 |
| -- | -- |
| getTree() => ITreeNode[] | 获取整棵树 |
| setTree(tree: ITreeNode[]) => void | 设置整棵树 |
| getLevel(node: ITreeNode) => number | 获取节点层级 |
| getChildren(node: ITreeNode): ITreeNode[] | 获取子节点 |
| selectNode(node: ITreeNode): void | 点击选择 |
| checkNode(node: ITreeNode): void | 勾选 |
| uncheckNode(node: ITreeNode): void | 取消勾选 |
| expandNode(node: ITreeNode): void | 展开 |
| collapseNode(node: ITreeNode): void | 收起 |
| toggleNode(node: ITreeNode): void | 切换展开/收起状态 |
| disableSelectNode(node: ITreeNode): void | 禁用点击选择 |
| disableCheckNode(node: ITreeNode): void | 禁用勾选 |
| disableToggleNode(node: ITreeNode): void | 禁用展开/收起 |
| insertBefore(parentNode: ITreeNode, node: ITreeNode, referenceNode: ITreeNode, cut: boolean = false): void | 插入节点 |
| removeNode(node: ITreeNode): void | 移除节点 |
| editNode(node: ITreeNode, label: string): void | 编辑节点内容 |
| getChildren(node: ITreeNode) => ITreeNode[] | 获取子节点 |
| getExpendedTree() => ComputedRef<IInnerTreeNode[]> | 获取展开的树 |
| getIndex(node: ITreeNode) => number | 获取节点的 index |
| getNode(node: ITreeNode) => IInnerTreeNode | 获取节点数据 |
| setNodeValue(node: IInnerTreeNode, key: keyof IInnerTreeNode, value: valueof<IInnerTreeNode>) => void | 设置节点属性 |

### useSelect

| 名称 | 描述 |
| -- | -- |
| selectNode(node: ITreeNode) => void | 点击选择 |

### useCheck

| 名称 | 描述 |
| -- | -- |
| checkNode(node: ITreeNode) => void | 勾选 |
| uncheckNode(node: ITreeNode) => void | 取消勾选 |
| toggleCheckNode(node: ITreeNode) => void | 取消勾选状态 |

### useToggle

| 名称 | 描述 |
| -- | -- |
| expandNode(node: ITreeNode) => void | 展开 |
| collapseNode(node: ITreeNode) => void | 收起 |
| toggleNode(node: ITreeNode) => void | 切换展开/收起状态 |

### useDisable

| 名称 | 描述 |
| -- | -- |
| disableSelectNode(node: ITreeNode) => void | 禁用点击选择 |
| disableCheckNode(node: ITreeNode) => void | 禁用勾选 |
| disableToggleNode(node: ITreeNode) => void | 禁用展开/收起 |
| enableSelectNode(node: ITreeNode) => void | 取消禁用点击选择 |
| enableCheckNode(node: ITreeNode) => void | 取消禁用勾选 |
| enableToggleNode(node: ITreeNode) => void | 取消禁用展开/收起 |

### useOperate

| insertBefore(parentNode: ITreeNode, node: ITreeNode, referenceNode: ITreeNode, cut: boolean = false) => void | 插入节点 |
| removeNode(node: ITreeNode) => void | 移除节点 |
| editNode(node: ITreeNode, label: string) => void | 编辑节点内容 |

## ITreeNode

Expand Down
99 changes: 0 additions & 99 deletions packages/devui-vue/devui/tree/src/core/tree-factory.ts

This file was deleted.

15 changes: 11 additions & 4 deletions packages/devui-vue/devui/tree/src/core/use-check.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Ref } from 'vue';
import { IInnerTreeNode, IUseCore } from './tree-factory-types';
import { IInnerTreeNode, IUseCore } from './use-tree-types';

export default function useCheck(data: Ref<IInnerTreeNode[]>, core: IUseCore) {
console.log('useCheck:', data, data.value);

const { setNodeValue } = core;
const { setNodeValue, getNode } = core;

const checkNode = (node: IInnerTreeNode): void => {
setNodeValue(node, 'checked', true);
Expand All @@ -14,8 +12,17 @@ export default function useCheck(data: Ref<IInnerTreeNode[]>, core: IUseCore) {
setNodeValue(node, 'checked', false);
}

const toggleCheckNode = (node: IInnerTreeNode): void => {
if (getNode(node).checked) {
setNodeValue(node, 'checked', false);
} else {
setNodeValue(node, 'checked', true);
}
}

return {
checkNode,
uncheckNode,
toggleCheckNode,
}
}
Loading