乐趣区

关于前端:纯前端也可以访问文件系统

前言

周末逛 github 的时候,发现咱们只须要在 github 域名上加上 1s 他就可能关上一个 vscode 窗口来浏览代码,比起在 github 仓库中查看更加不便

而后我就想网页端 vscode 能不能关上我本地的我的项目呢,带着这个纳闷我关上了网页版vscode,它竟然真的能够关上我本地的我的项目代码!

难道又出了新的 API 让前端的能力更进一步了?关上 MDN 查了一下相干文档,发现了几个新的 API

showOpenFilePicker

用来抉择文件

语法

showOpenFilePicker()

参数

  • options:(可选)蕴含以下属性

    • multiple:布尔值,默认为 false。为true 示意容许用户抉择多个文件
    • excludeAcceptAllOption:布尔值,默认为false。默认状况下,文件选择器带有一个容许用户抉择所有类型文件的过滤选项(开展于文件类型选项中)。设置此选项为 true 以使该过滤选项不可用。
    • types:示意容许抉择的文件类型的数组

返回值

返回一个 promise 对象,会兑现一个蕴含 FileSystemFileHandle 对象的 Array 数组。

体验

<template>
  <div class="open_file" @click="openFile"> 关上文件 </div>
</template>

<script setup lang="ts">
const openFile = async () => {const res = await window.showOpenFilePicker();
  console.log(res);
};
</script>

默认只能关上一个文件,能够传入 multiple:true 关上多个文件

showDirectoryPicker

用来抉择目录

语法

属于浏览器全局办法,间接调用即可

showDirectoryPicker()

参数

  • options:(可选)蕴含以下属性

    • multiple:布尔值,默认为 false。为true 示意容许用户抉择多个文件
    • excludeAcceptAllOption:布尔值,默认为false。默认状况下,文件选择器带有一个容许用户抉择所有类型文件的过滤选项(开展于文件类型选项中)。设置此选项为 true 以使该过滤选项不可用。
    • types:示意容许抉择的文件类型的数组

返回值

返回一个 promise 对象,会兑现一个蕴含 FileSystemFileHandle 对象的 Array 数组。

体验

<template>
  <div class="open_file" @click="openFile"> 关上文件 </div>
  <div class="open_file" @click="openDir"> 关上文件夹 </div>
</template>

<script setup lang="ts">
const openFile = async () => {
  const res = await window.showOpenFilePicker({// multiple: true,});
  console.log(res.length);
};

const openDir = async () => {const res = await window.showDirectoryPicker();
  console.log(res);
};
</script>

扩大

FileSystemFileHandle

FileSystemFileHandle提供了一些办法能够用来获取和操作文件

  • getFile:返回一个 Promise 对象,用于获取文件;
  • createSyncAccessHandle:返回一个 FileSystemSyncAccessHandle 对象,用于同步拜访文件;
  • createWritable:返回一个 Promise 对象,用于创立一个可写流,用于写入文件;

FileSystemDirectoryHandle

FileSystemDirectoryHandle对象是一个代表文件系统中的目录的对象,它同样提供了办法来获取和操作目录

  • entries:返回一个 AsyncIterable 对象,用于获取目录中的所有文件和目录;
  • keys:返回一个 AsyncIterable 对象,用于获取目录中的所有文件和目录的名称;
  • values:返回一个 AsyncIterable 对象,用于获取目录中的所有文件和目录的 FileSystemHandle 对象;
  • getFileHandle:返回一个 Promise 对象,用于获取目录中的文件;
  • getDirectoryHandle:返回一个 Promise 对象,用于获取目录中的目录;
  • removeEntry:返回一个 Promise 对象,用于删除目录中的文件或目录;
  • resolve:返回一个 Promise 对象,用于获取目录中的文件或目录;

entrieskeysvalues这三个办法都是用来获取目录中的所有文件和目录的,它们返回的都是一个 AsyncIterable 对象,咱们能够通过 for await...of 语法来遍历它。

开发编辑器

理解完这些知识点,咱们就能够来开发一个简陋网页版编辑器了,初期只蕴含关上文件、关上文件夹、查看文件、切换文件

编辑器大略长这样:

关上文件夹

const openDir = async () => {const res = await window.showDirectoryPicker({});
  const detalAction = async (obj: any) => {if (obj.entries) {const dirs = obj.entries();
      for await (const entry of dirs) {if (entry[1].entries) {
          // 文件夹,递归解决
          detalAction(entry[1]);
        } else {
          // 文件
          fileList.value.push({name: entry[0],
            path: obj.name,
            fileHandle: entry[1],
          });
        }
      }
    }
  };
  await detalAction(res);
  showCode(fileList.value[0], 0);
  console.log("--fileList--", fileList);
};

这里次要是递归解决文件夹,返回一个文件列表

读取文件内容

const showCode = async (item: any, index: number) => {const file = await item.fileHandle.getFile();
  const text = await file.text();
  codeText.value = text;
  currentIndex.value = index;
};

展现文件内容

应用 highlight.js 来高亮展现代码

<div class="show_code">
  <pre v-highlight>
        <code class="lang-dart">
            {{codeText}}
        </code>
   </pre>
</div>

最终成果如下:

想不到吧,这种性能当初纯前端就可能实现了,当然还能够做的更简单一点,包含批改保留等性能,保留能够应用showSaveFilePickerAPI,它能够写入文件,同样是返回一个promise。感兴趣的能够试着欠缺编辑器的性能。

退出移动版