文件系统设计 - 开发文件系统 Store (上篇)

devtools/2024/9/24 4:32:13/

本节开始,我们将从最核心基础的文件系统进行设计实现,构建文件系统Store

  • 一个基础的响应式Store类
  • 设计文件系统类接口
  • 小结

一个基础的响应式Store类

Vue3 开始,Vue响应式借助Proxy重构后,整个响应式系统的应用变得非常的灵活,虽然目前业界依旧有 Pinia 等响应式管理库,但其本质依旧是在借助Vue的响应式API进行设计实现;所以很多时候其实并非需要第三方的响应式管理库,如果只是简单的响应式处理直接借助 Vue 的响应式API即可。

关于Vue3 的响应式实现细节,大家可以参考网上很多的Vue原理解析文章,或者大家有兴趣可以在下方留言,后面也可以出一期从0手写mini-vue3 源码的专栏

这里我们便借助 Vue 的响应式API封装一个具有响应式State管理的基类

import { reactive, UnwrapNestedRefs } from 'vue'export abstract class Store<T extends Record<string, unknown>> {state: UnwrapNestedRefs<T>;constructor(state: T) {this.state = reactive(state);}
}

设计文件系统类接口

web端的编辑器虽然可以借助 File System Access API 对本地文件进行操作,但是因其兼容性问题,目前Web编辑器的文件还是存在内存中的,将文件以树型结构在内存中进行存储维护,所以首先我们先明确文件系统的主要作用是: 管理内存中的文件树; 这里的管理主要包括以下部分:

  • 创建文件/文件夹
  • 删除文件/文件夹
  • 查找文件/文件夹
  • 移动文件/文件夹
  • 文件/文件夹重命名
  • 文件写入

首先,我们需要先设计出文件在内存中进行管理的数据结构定义

// 定义文件的类型
export const enum FileType {File,Directory,
}// 文件的结构定义
export interface IFileSystemItem {filename: string;  	/* 文件名 */type: FileType.File; 	/* 文件类型 */code: string;			/* 文件的代码 */ext: string;			/* 文件的扩展名 */fullPath: string;		/* 文件的完整路径 */status: number;		/* 文件当前的状态: 用于记录当前对文件的操作 */cacheBuffer: string | null  /** 文件内容缓冲区 */;language?: string;	/* 代码语言 */readonly?: boolean;	/* 文件是否只读 */visible?: boolean;	/* 文件是否在文件树中显示 */
}// 目录的结构定义
export interface IDirectoryItem extends Record<string, unknown> {filename: string; 			/* 文件名 */type: FileType.Directory;		/* 文件类型 */fullPath: string;				/* 文件完整路径 */status: number;				/* 文件夹当前状态 */readonly?: boolean;			/* 文件夹是否只读 */visible?: boolean;			/* 文件夹是否在文件树中可见 */children: (IFileSystemItem | IDirectoryItem)[];	/* 文件夹下的子文件 */
}

定义好文件系统在内存中的存储结构后,我们还需要定义文件系统的响应式 State 中的数据结构

export type FileSystemState = {/* 文件树 - 单根文件夹 */files: IDirectoryItem;/* 文件Map映射,方便快速的根据文件路径查找文件 */fileMap: Map<string, IFileSystemItem | IDirectoryItem>;
};

对于文件的操作,我们将通过文件的 status 字段进行记录,比如文件编辑、文件重命名等;那如何通过一个字段来记录多种状态呢? 这里我们采用二进制位Mask来处理,首先我们先定义几个基础的文件操作:

export const enum FileOperation {Editing = 0b00000001,Rename = 0b00000010,Delete = 0b00000100,Move = 0b00001000,Create = 0b00010000,
}

关于如何通过二进制位Mask来记录不同的状态,我们将在下篇文章中具体实现文件系统进行介绍

完成以上步骤之后,现在我们可以开始定义文件系统的接口描述了,文件系统Store 是一个继承自响应式基类的文件管理子类,处理响应式文件State 数据之外,还有相关的文件操作逻辑:

export interface FileSystemProvider {/* 响应式的文件数据 */state: FileSystemState;/*** 创建文件* @param path 文件路径 uri* @param content 文件内容* @param readonly 是否只读* @param visible 是否可见*/createFile(path: Uri,content: string,readonly?: boolean,visible?: boolean): IFileSystemItem;/*** 创建目录* @param path 目录 Uri* @param readonly 是否只读* @param visible 是否可见*/createDirectory(path: Uri,readonly?: boolean,visible?: boolean): IDirectoryItem;/*** 读取文件内容* @param path 文件路径 uri*/readFile(path: Uri | string): IFileSystemItem | IDirectoryItem | null;/*** 写入文件数据* @param path 文件路径 uri* @param content 文件内容* @returns 文件变更状态数据*/writeFile(path: Uri | string,content: string,isBuffer?: boolean): ChangeFileState | null;/*** 删除文件或目录* @param file 文件对象* @returns 文件变更状态数据*/delete(file: IFileSystemItem | IDirectoryItem): ChangeFileState | null;/*** 文件重命名* @param file 文件对象* @param newName 文件名* @returns 文件变更状态数据*/renameFile(file: IFileSystemItem, newName: string): ChangeFileState;/*** 文件夹重命名* @param folder 文件对象* @param newName 文件名* @returns 文件变更状态数据*/renameFolder(folder: IDirectoryItem, newName: string): ChangeFileState[];/*** 移动文件* @param sourcePath 源路径* @param targetPath 目标路径* @returns 文件变更状态数据数组*/moveFile: (sourcePath: Uri | string,targetPath: Uri | string) => ChangeFileState[] | null;/*** 为文件对象添加操作* @param file 文件对象* @param operator 操作*/addOperator: (file: IFileSystemItem | IDirectoryItem,operator: FileOperation) => void;/*** 为文件对象移除操作* @param file 文件对象* @param operator 操作*/removeOperator: (file: IFileSystemItem | IDirectoryItem,operator: FileOperation) => void;
}

小结

这一章我们正式开始组件库的开发,组件的开发我认为最重要的不是组件如何渲染,而是数据如何维护和管理;
从这章开始我们介绍的是整个编辑器组件的核心:文件系统; 我们将按照面向接口编程的方式,逐步设计和实现文件系统的管理和操作。这一章节我们通过TS类型定义设计实现了文件系统相关的接口定义,大家也可以根据目前文件系统的接口定义,尝试实现文件系统管理类。

如果大家在开发过程中有任何的问题欢迎下方留言评论,我将尽快为大家解答;加油!


http://www.ppmy.cn/devtools/116324.html

相关文章

Java集合(Map篇)

一.Map a.使用Map i.键值&#xff08;key-value&#xff09;映射表的数据结构&#xff0c;能高效通过key快速查找value&#xff08;元素&#xff09;。 ii.Map是一个接口&#xff0c;最常用的实现类是HashMap。 iii.重复放入k-v不会有问题&#xff0c;但是一个…

Opencv图像预处理(三)

blur&#xff08;均值滤波&#xff09; 一种常用的图像平滑处理方法&#xff0c;通过将像素的领域内像素值取平均来减少图像中的噪声&#xff0c;从而达到图像平滑的效果&#xff0c;图像会更模糊。 using System; using System.Collections.Generic; using System.Linq; usi…

Set 和 Map 的模拟实现

1、引言 在数据结构与算法的学习与实践中&#xff0c;关联容器&#xff08;associative containers&#xff09;是不可忽视的重要工具。作为高效管理数据的一类容器&#xff0c;C 标准库中的 set 和 map 在现代软件开发中扮演着关键角色。这两个容器通过平衡二叉搜索树&#x…

2024年9月21日---关于Maven

第一节&#xff1a;maven工具的简介 1.1 开发过程中遇到的问题 1、都是同样的代码&#xff0c;为什么在我的机器上可以编译执行&#xff0c;而在他的机器上就不行&#xff1f; 2、为什么在我的机器上可以正常打包&#xff0c;而配置管理员却打不出来? 3、项目组加入了新的人…

Qt窗口——QToolBar

文章目录 工具栏创建工具栏设置toolTip工具栏配合菜单栏工具栏浮动状态 工具栏 QToolBar工具栏是应用程序中集成各种功能实现快捷键使用的一个区域。 可以有多个&#xff0c;也可以没有。 创建工具栏 #include "mainwindow.h" #include "ui_mainwindow.h&qu…

vue项目加载cdn失败解决方法

注释index.html文件中 找到vue.config.js文件注释、

卷积神经网络(Convolutional Neural Network,CNN)

CNN网络主要有三部分构成&#xff1a;卷积层、池化层和全连接层构成&#xff0c;其中卷积层负责提取图像中的局部特征&#xff1b;池化层用来大幅降低参数量级(降维)&#xff1b;全连接层类似神经网络的部分&#xff0c;用来输出想要的结果。 卷积思想 卷积Convolution&#x…

前端css样式覆盖

.detail .grid .active 的样式会覆盖 .detail .grid .bgorange .active 在CSS中&#xff0c;当多个选择器应用于同一元素时&#xff0c;会根据一定的优先级规则决定哪个样式会被应用。 CSS选择器的优先级规则如下&#xff1a; 内联样式&#xff08;在HTML元素的style属性中定…