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

前言

周末逛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。感兴趣的能够试着欠缺编辑器的性能。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理