Skip to content

Vue3+Ts 模仿一个 IDE 中的文件树

约 992 字大约 3 分钟

VueTypeScript

2024-12-31

使用 Vue3 做一个能够通过选定的本地文件夹生成一个类似 IDE 左侧的文件树,同时点击文件可显示基本信息的功能。

24123101_01.png

本项目已发布到开源仓库 filetree,代码对应文件为 App.vueTreeNode.vue。也可以通过 这个链接快速访问本项目。

以下是对核心代码的讲解。

1. 文件处理

要实现文件树最大的核心在于 解析文件夹结构构建文件树

1.1 定义文件树节点

文件树与数据结构中的树类似,将每个文件抽象为一个节点,节点包含 文件名、路径、子文件、折叠状态

interface FileItem {
  name: string;
  path: string;
  children?: FileItem[];
  collapsed?: boolean;
}

1.2 构建文件树

将一个 FileList 对象转换成一个树形结构的 FileItem 数组。 每个 FileItem 代表一个文件或文件夹,并包含其子文件或子文件夹。

1.3 构建文件路径和 File 对象的映射

构建 fileMap,用于后续文件信息的展示。

const buildFileMap = (files: FileList) => {
  fileMap.value = {};
  for (let i = 0; i < files.length; i++) {
    const file = files[i];
    // 将文件路径作为键,文件对象作为值
    fileMap.value[file.webkitRelativePath] = file;
  }
};

1.4 处理文件夹选择

handleFolderSelect 方法绑定在 input[type=file] 中。

2. 文件树组件

文件树组件 TreeNode 对传入的 fileTreefileMap 进行递归渲染。
文件树 props :

const props = defineProps<{
    files: FileItem[];
    fileMap: Record<string, File>; // 用于存储文件路径和 File 对象的映射
}>();

TreeNode.vue :

因为还需要根据 文件后缀匹配文件图标 ,同时文件夹需要能够 折叠/展开,因此还需进行 collapsed 判断。 图标使用 iconify ,通过 <Icon icon="iconname"/> 进行图标渲染。

// icon 对象
interface IconConfig {
  type: string; // 文件后缀
  icon: string; // 图标
}
// 获取icon
const getFileIcon = (filename: string): string | undefined => {
// 获取文件后缀
    const fileExtension = filename.split('.').pop()?.toLowerCase();
    // 在 icon.json 中查找对应的图标
    const iconConfig = icons.find((icon: IconConfig) => icon.type === fileExtension);
    // 返回图标,如果未找到则返回 默认图标
    return iconConfig ? iconConfig.icon : 'flat-color-icons:document';
}

icons.find()icons 来源于自定义的 icon.json

[
  {
    "type": "pdf",
    "icon": "vscode-icons:file-type-pdf2"
  },
  {
    "type": "md",
    "icon": "skill-icons:markdown-dark"
  },
  {
    "type": "docx",
    "icon": "vscode-icons:file-type-word"
  }
]