基于 Vue3+TS+TailwindCSS 实现一个 Terminal

662 阅读2分钟

项目体验链接:term.mphy.me

关于

前几天图发奇想,想写一个 mini terminal,作为新手来学习和实践 Vue3 还是很好的。于是搜了一下 Github 上的开源项目,确实有,但都只是实现了一些很基本的输入输出,也就是说没有 mkdir、touch、ls、pwd 命令。

这里无意混淆大家 terminal、shell、kernel 的概念,只是为了简化项目描述,把这些指令也纳入 terminal 里了,详细的区别可以自行搜索。

所以就想动手实现一下,核心思想是利用 M 叉树,模拟 Linux 的目录系统,实现了创建文件和目录、目录跳转等基本功能。

技术栈

  • Vue3(composition api + script setup) + TS + Vite
  • Pinia(状态管理)
  • unplugin-auto-import + unplugin-vue-components(组件和 API 的自动按需导入)

特性

  • 实现了基本的 linux 命令:pwd、ls、mkdir、touch、cd、clear
  • 窗口拖拽功能以及防止过度拖拽的指令
  • 模拟 MacOS 的样式

页面初始化:可拖拽、移动、关闭终端窗口 image.png

清屏: image.png

基本的 ls、pwd、mkdir、touch 指令:(更多指令欢迎探索和 PR)

image.png

原理

文件结构使用了 N 叉树的数据结构,依据这个结构,实现了包含但不限于 mdir、touch、cd 等命令,还可以实现 autojump、search 等命令,只要是能在真实物理机上的大部分和文件相关的命令,都能实现(有待完成)。

interface Directory {
  id: number  // id
  name: string // 当前目录名称
  files: string[] // 当前目录下的文件列表
  directories: Directory[]   // 当前目录下的子目录列表,同时也是指向子目录的指针
  previous: Directory | null // 指向父目录的指针
}

例如,我设计了 previous 指针,指向它的父节点,这样就实现了 cd .. 命令:

// 模拟 cd ..
export const cdBack = () => {
  if (uds().dir.previous) {
    uds().dir = uds().dir.previous as Directory
  }
}

又比如,一个暂未实现的命令,echo 123 > file.txt,即将 123 这串字符串输入到 file.txt 文件中,可以改造 files 数据结构为:

interface file {
  name: string    // 文件名
  content: string // 文件内容
}

这样就可以实现文件的读写操作了。

总结

本文是 Vue3-Terminal 这个图发奇想的小 demo 的推广,希望帮助正在学习 Vue3 + TS 的小伙伴进一步熟悉知识点。同时,你也能学到数据结构与算法的相关知识。