Terminal Web终端基础(Web IDE 技术探索 二)

Terminal是web终端技术,类似cmd命令窗口,Webcontainer 中推荐使用的是Xterm.js,这里就不细说Xterm.js 的使用了,我们使用第三方库来实现(原生确实有点难用)。

vue-web-terminal

一个由 Vue 构建的支持多内容格式显示的网页端命令行窗口插件,支持表格、json、代码等多种消息格式,支持自定义消息样式、命令行库、键入搜索提示等,模拟原生终端窗口支持 ← → 光标切换和 ↑ ↓ 历史命令切换。其完善的API、中文文档、拖拽、缩放、实时回显等功能是我选择其的原因之一。

在线体验地址

github 地址

中文文档

javascript 复制代码
npm install vue-web-terminal@3 --save 
javascript 复制代码
import Terminal from 'vue-web-terminal'
//  3.2.0 及 2.1.13 以后版本需要引入此样式,之前版本无需引入主题样式
import 'vue-web-terminal/lib/theme/dark.css'

// for vue3
const app = createApp(App).use(Terminal)
javascript 复制代码
<template>
  <terminal name="my-terminal" @exec-cmd="onExecCmd"></terminal>
</template>

<script setup>
function onExecCmd(cmd) {
  console.log(cmd);
}
</script>

切换主题

主题的核心是导入的style 文件里面自定义的css变量,因此,我们可以通过控制导入的文件实现主题切换:

经过分析观察,两个文件的节点是一样的,无法通过js控制,因此,复制文件到外部文件夹,并添加标识,main.js 中引入外部文件:

javascript 复制代码
function changeTheme() {
  document
    .querySelector("html")
    .setAttribute("t-theme", dark.value ? "dark" : "lignt");

  dark.value = !dark.value;
}

这样更利于我们自定义主题,直接在原有基础上进行拓展即可。

个性化配置

show-header 是否显示头部

context 上下文内容(Root)

context-suffix 上下文后缀符号(@)

​编辑

...更多配置项,大家去官网看下,比较简单,就不细说了。

事件列表

事件这块我就说一个 exec-cmd:执行自定义命令时触发。successfailed为回调函数,必须调用两个回调其中之一才会回显failed回调参数为一个string,exec-cmd的success回调参数支持多种数据类型,不同数据类型执行逻辑也会不同:

  • 不传任何参数,立即结束本次执行
  • 传入一个消息对象,将会向记录中追加一条消息,并立即结束本次执行
  • 传入一个消息对象数组,将会向记录中追加多条消息,并立即结束本次执行
  • 传入一个TerminalFlash对象,将会进入实时回显处理逻辑,本次执行并不会结束,直到调用finish()
  • 传入一个TerminalAsk对象,将会进入用户询问输入处理逻辑,本次执行并不会结束,直到调用finish()
javascript 复制代码
function onExecCmd(cmdKey, command, success, failed, name) {}
javascript 复制代码
function onExecCmd(cmdKey, command, success, failed, name) {
  success(); // 什么都不传,直接结束
}
javascript 复制代码
function onExecCmd(cmdKey, command, success, failed, name) {
  success({ content: "hello world" }); // 传一个消息对象
}
javascript 复制代码
function onExecCmd(cmdKey, command, success, failed, name) {
  success([{ content: "hello world" }, { content: "hello javascript" }]); // 传一个消息对象数组
}
javascript 复制代码
import { TerminalFlash } from "vue-web-terminal";
const flash = new TerminalFlash();
function onExecCmd(cmdKey, command, success, failed, name) {
  let count = 0;
  success(flash); // 传一个 TerminalFlash

  let flashInterval = setInterval(() => {
    //  显示数据调用 flag.flush(string)
    flash.flush(`This is flash content: ${count}`);

    if (++count >= 20) {
      clearInterval(flashInterval);
      //  结束回显调用 flag.finish()
      flash.finish();
    }
  }, 200);
}
javascript 复制代码
import { TerminalFlash, TerminalAsk } from "vue-web-terminal";
const flash = new TerminalFlash();
const asker = new TerminalAsk();
function onExecCmd(cmdKey, command, success, failed, name) {
  success(asker); // 传一个 TerminalAsk
  // 询问账号
  asker.ask({
    question: "Please input user name:",
    callback: askPassword,
  });

  function askPassword(value) {
    console.log("输入的username ==>", value);
    asker.ask({
      question: "Please input password: ",
      autoReview: true,
      isPassword: true,
      callback: (pass) => {
        //    do something
        console.log("输入的password ==>", pass);
        asker.finish();
      },
    });
  }
}

后面两种复杂的情况在构建应用时常用到,大家多练习下。还支持插槽,这块大家自己看下文档,应该也能学会,就不细说了。

Terminal API

API无非就是主动向终端发送消息,具体api 可以看官网哈

javascript 复制代码
TerminalApi.textEditorOpen('my-terminal', {
    content: 'This is the preset content',
    onClose: (value, options) => {
        console.log('Final content: ', value, "options:", options)
    }
})

在xshell中,可以在终端直接编辑 nginx配置文件,vue-web-terminal 支持调用textEditorOpen方法,打开编辑器:

与WebContainer结合

terminal只是网页端命令行窗口插件,并不具备实际的命令执行能力。当我输入 node -v 的时候,terminal的显示值,还需要通过 success 决定。

因此,需要与webcontainer 结合,使得 terminal的输入,转化为 spawn 的参数,获取到output 输出流后,再回显到 terminal上。

javascript 复制代码
async function onExecCmd(cmdKey, command, success, failed, name) {
  // 将命令行拆分为数组
  let argus = command.split(" ");

  let res = await wcInstance.spawn(argus[0], argus.slice(1));

  // 读取流
  res.output.pipeTo(
    new WritableStream({
      write(data) {
        success(data);
      },
    })
  );
}

这只是一个简单的示例哈,并不是所有的回显都是 success,也并不是所有的回显都是直接显示文本,例如 ls 查看文件列表,使用表格更合适,npm install 使用实时回显flash 更合适。

总结

确实vue-web-terminal使用起来更加方便,封装的API、事件列表为我们省去了很多麻烦。使用起来也不难,大家多看文档即可学会。但是大家要记住哈,terminal仅是终端展示用,实际的执行能力还是依靠webContainer,因此,两者的参数传递、数据回显需要做精细化处理。

相关推荐
茶茶只知道学习几秒前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css
蒟蒻的贤3 分钟前
Web APIs 第二天
开发语言·前端·javascript
清灵xmf7 分钟前
揭开 Vue 3 中大量使用 ref 的隐藏危机
前端·javascript·vue.js·ref
su1ka11112 分钟前
re题(35)BUUCTF-[FlareOn4]IgniteMe
前端
测试界柠檬14 分钟前
面试真题 | web自动化关闭浏览器,quit()和close()的区别
前端·自动化测试·软件测试·功能测试·程序人生·面试·自动化
多多*15 分钟前
OJ在线评测系统 登录页面开发 前端后端联调实现全栈开发
linux·服务器·前端·ubuntu·docker·前端框架
2301_8010741515 分钟前
TypeScript异常处理
前端·javascript·typescript
ᅠᅠᅠ@16 分钟前
异常枚举;
开发语言·javascript·ecmascript
小阿飞_16 分钟前
报错合计-1
前端
caperxi18 分钟前
前端开发中的防抖与节流
前端·javascript·html