网页版代码编辑器实现

接着前几天写的博客https://blog.csdn.net/woyebuzhidao321/article/details/131495855,提到了涉及vscode网页版工作区创建的api,这两天一时兴起,搞了一个网页版的代码编辑器,如果在2020年10月之前,实现一个网页版代码编辑器可能是天方夜谭,由于网页端操作本地文件的困难,很难搞得出,直到File System Access API的出现,打破了原来的瓶颈。

2020年10月 Chrome 86 重要更新

Chrome 86 在2020年10月推出了稳定版,现已全面应用于Android、Chrome OS、Linux、macOS 和 Windows等平台,我们一起来看下这次的重要更新。

若要看全部更新,请移步(https://www.chromestatus.com/features#milestone=86)。

新增稳定功能
文件系统访问

还记得Chrome 83中的本地文件系统吗,当时的试验功能,现已稳定。通过调用 showOpenFilePicker 方法,你可以唤起文件选择窗口,进而通过返回的文件句柄对文件进行读写。代码如下:

const pickerOpts = {
    
    
  types: [
    {
    
    
      description: "Images",
      accept: {
    
    
        "image/*": [".png", ".gif", ".jpeg", ".jpg"],
      },
    },
  ],
  excludeAcceptAllOption: true,
  multiple: false,
};
// create a reference for our file handle
let fileHandle;

async function getFile() {
    
    
  // open file picker, destructure the one element returned array
  [fileHandle] = await window.showOpenFilePicker(pickerOpts);

  // run code with our fileHandle
}

官方文档地址:
https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker

vscode网页版也是在此之后出现的。https://insiders.vscode.dev/

于是我照着大框实现了一个demo
Demo效果图
在这里插入图片描述
基于文件的增、删、改、查。读写速度很nice

打开文件夹

首先打开一个代码目录

$('#openFolderBtn')[0].addEventListener('click', async () => {
    
    
	try {
    
    
	// // 得到异步迭代器
		dirHandle = await window.showDirectoryPicker();

		const createTree = async () => {
    
    
			const root = await createTreeModel(dirHandle);
			fileArr = root;
			treeInit();
		}
		createTree();
		
	} catch (err) {
    
    
		console.log(err)
	}
})

在这里插入图片描述
这是会弹出一个文件弹窗
window.showDirectoryPicker是异步的 返回一个文件句柄,选中文件之后会出现提示
在这里插入图片描述
创建树的数据结构
在这里插入图片描述

读取文件

// 读取文件
async function reader() {
    
    
	if (fileHandle) {
    
    
		let file = await fileHandle.getFile();
		fileName.innerText = file.name;

		let reader = new FileReader();
		reader.onload = function (event) {
    
    
			let contents = escapeHtml(event.target.result);
			$("#textbox")[0].innerHTML = `<pre><code id="code">${
      
      contents}</code></pre>`;
			// hljs.highlightAll();
			hljs.highlightBlock($("#code")[0])
		};
		reader.readAsText(file);
	}
}

fileHandle是对应的文件句柄,通过调用getFile方法拿到文件,然后通过FileReader构造函数去读取文件内容并作展示

打开文件

如何单独打开一个本地文件

$('#openfile')[0].addEventListener('click', async () => {
    
    
	try {
    
    
		const openFileHandle = await window.showOpenFilePicker({
    
    
			types: [{
    
    
				accept: {
    
    
					"text/plain": [".txt"]
				}
			}],
			multiple: false
		});

		fileHandle = openFileHandle[0];
		reader();
	} catch (err) {
    
    
		console.log(err);
	}
})

选取一个文件并打开
在这里插入图片描述

如何创建一个文件夹

$("#createFolder")[0].addEventListener('click', async (e) => {
    
    
	const folderName = prompt('请输入文件夹名称');
	if (folderName) {
    
    
		await dirHandle.getDirectoryHandle(folderName, {
    
     create: true });
		console.log('文件夹创建成功');
		fileArrFlat = [];
		fileArr = await createTreeModel(dirHandle);
		treeInit();
	}
})

dirHandle是window.showDirectoryPicker返回的文件句柄,通过调用getDirectoryHandle方法创建。

创建一个文件

// 创建文件
$("#createFile")[0].addEventListener('click', async (e) => {
    
    
	const fileName = prompt('请输入文件名称');
	if (fileName) {
    
    
		try {
    
    
			if (!(await dirHandle.queryPermission()) === 'granted') {
    
    
				alert('文件不允许读写!');
				return;
			}
			const targetFile = await dirHandle.getFileHandle(fileName, {
    
     create: true });

			fileArrFlat = [];
			fileArr = await createTreeModel(dirHandle);
			treeInit();
		} catch (err) {
    
    
			console.log(err)
		}
	}
})

另存为文件并写入内容

// 另存为文件
	$("#textbox")[0].addEventListener('keydown', async (e) => {
    
    
		if (e.ctrlKey && e.which == 83) {
    
    
			e.preventDefault;
			console.log('文件另存为', $("#textbox")[0].innerText)
			try {
    
    
				fileHandle = await window.showSaveFilePicker({
    
    
					types: [{
    
    
						accept: {
    
    
							"text/plain": [".txt"]
						}
					}],
					multiple: false
				});
				const w$ = await fileHandle.createWritable();
				await w$.write($("#textbox")[0].innerText);
				await w$.close();
			} catch (err) {
    
    
				console.log(err);
			}

			return false;
		}
	}, false)

fileHandle文件句柄 提供了createWritable方法,对文件进行写入内容。

代码高亮部分使用的是highLight.js,这样一个最初版的网页版代码编辑器就搞定了

其兼容性
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/woyebuzhidao321/article/details/131627691