Skip to content

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

参数名类型必填说明
pathsstring[]相对路径列表
optionsSortOptions排序选项

SortOptions

属性类型说明
localestring排序 locale,默认 'zh-CN'
foldersFirstboolean是否目录在前,默认 true

返回值

类型说明
TreeNode[]树形节点数组

TreeNode 属性

属性类型说明
keystring节点唯一标识(完整路径)
labelstring节点显示文本(文件名/目录名)
childrenTreeNode[]子节点数组
selectableboolean是否可选中(叶子文件节点为 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>

排序规则

默认排序规则:

  1. 目录优先:所有目录排在文件前面
  2. 字母排序:同级节点按文件名 localeCompare 排序
  3. 递归排序:递归对所有子节点进行排序

注意事项

  • 路径中的反斜杠 \ 会自动转换为正斜杠 /
  • 路径开头的斜杠会被忽略
  • 空路径会被过滤掉
  • 叶子文件节点的 selectable 属性为 true
  • 目录节点(有子节点的)的 selectableundefined