pathsToTreeNodes
将扁平路径列表转换为树形节点
树形结构:
📁src
📁components
📄Button.vue可选
📄Input.vue可选
📁utils
📄helper.ts可选
📄main.ts可选
📄package.json可选
📄README.md可选
JSON 结果:
[
{
"key": "src",
"label": "src",
"children": [
{
"key": "src/components",
"label": "components",
"children": [
{
"key": "src/components/Button.vue",
"label": "Button.vue",
"selectable": true
},
{
"key": "src/components/Input.vue",
"label": "Input.vue",
"selectable": true
}
],
"selectable": false
},
{
"key": "src/utils",
"label": "utils",
"children": [
{
"key": "src/utils/helper.ts",
"label": "helper.ts",
"selectable": true
}
],
"selectable": false
},
{
"key": "src/main.ts",
"label": "main.ts",
"selectable": true
}
],
"selectable": false
},
{
"key": "package.json",
"label": "package.json",
"selectable": true
},
{
"key": "README.md",
"label": "README.md",
"selectable": true
}
]函数签名
typescript
interface TreeNode {
key: string
label: string
children?: TreeNode[]
selectable?: boolean
disabled?: boolean
[key: string]: any
}
interface SortOptions {
locale?: string
foldersFirst?: boolean
}
function pathsToTreeNodes(
paths: string[],
options?: SortOptions
): TreeNode[]
function pathsToTreeNodesWithTransform<T>(
paths: string[],
transform: (entry, children?) => T,
options?: SortOptions
): T[]参数
pathsToTreeNodes
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
paths | string[] | 是 | 相对路径列表 |
options | SortOptions | 否 | 排序选项 |
SortOptions
| 属性 | 类型 | 说明 |
|---|---|---|
locale | string | 排序 locale,默认 'zh-CN' |
foldersFirst | boolean | 是否目录在前,默认 true |
返回值
| 类型 | 说明 |
|---|---|
TreeNode[] | 树形节点数组 |
TreeNode 属性
| 属性 | 类型 | 说明 |
|---|---|---|
key | string | 节点唯一标识(完整路径) |
label | string | 节点显示文本(文件名/目录名) |
children | TreeNode[] | 子节点数组 |
selectable | boolean | 是否可选中(叶子文件节点为 true) |
使用示例
基本用法
typescript
import { pathsToTreeNodes } from 'zcw-shared/functions/tree/pathsToTreeNodes'
const paths = [
'src/components/Button.vue',
'src/components/Input.vue',
'src/utils/helper.ts',
'package.json'
]
const tree = pathsToTreeNodes(paths)自定义排序
typescript
// 英文排序
const tree = pathsToTreeNodes(paths, { locale: 'en-US' })
// 文件在前
const tree = pathsToTreeNodes(paths, { foldersFirst: false })自定义节点转换
typescript
import { pathsToTreeNodesWithTransform } from 'zcw-shared/functions/tree/pathsToTreeNodes'
interface CustomNode {
id: string
name: string
isFile: boolean
children?: CustomNode[]
}
const tree = pathsToTreeNodesWithTransform<CustomNode>(
paths,
(entry, children) => ({
id: entry.full,
name: entry.seg,
isFile: entry.isFile,
children
})
)在文件树组件中使用
vue
<template>
<div class="file-tree">
<tree-item
v-for="node in treeData"
:key="node.key"
:node="node"
@select="handleSelect"
/>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { pathsToTreeNodes } from 'zcw-shared/functions/tree/pathsToTreeNodes'
const props = defineProps<{
files: string[]
}>()
const treeData = computed(() => pathsToTreeNodes(props.files))
function handleSelect(node: TreeNode) {
if (node.selectable) {
console.log('选中文件:', node.key)
}
}
</script>排序规则
默认排序规则:
- 目录优先:所有目录排在文件前面
- 字母排序:同级节点按文件名 localeCompare 排序
- 递归排序:递归对所有子节点进行排序
注意事项
- 路径中的反斜杠
\会自动转换为正斜杠/ - 路径开头的斜杠会被忽略
- 空路径会被过滤掉
- 叶子文件节点的
selectable属性为true - 目录节点(有子节点的)的
selectable为undefined