xterm.js官网
借鉴学习案例

一.筹备工作

  • npm install xterm
  • npm install xterm-addon-fit

    二.初始引入渲染

    import { Terminal } from 'xterm'import { FitAddon } from 'xterm-addon-fit'import 'xterm/css/xterm.css'let term = new Terminal({  // 渲染类型  rendererType: 'canvas',  //   是否禁用输出  disableStdin: false,  cursorStyle: 'underline',  //   启用时光标将设置为下一行的结尾  convertEol: true,  // 终端中的回滚量  scrollback: 10,  fontSize: 14,  rows: 20,  // 光标闪动  cursorBlink: true,  theme: {    //   字体    foreground: '#ffffff',    background: '#000000',    // 光标    cursor: 'help',    lineHeight: 18,  },})// 换行并输出起始符 $term.prompt = () => {  term.write(`\r\n${terminalTitleTemplate}:`)}// 进行适应容器元素大小let fitAddon = new FitAddon()term.loadAddon(fitAddon)fitAddon.fit()

    三.重点来了,onData的应用能够输出中文且按高低键应用历史命令的时候不会光标串行笼罩之前的终端提示符

    const keyAction = (){// 定义变量获取整行数据let currentLineData = ''// 历史行输出数据let historyLineData = [] let last = 0  // 使其可能输出汉字  term.onData(async key => {   //enter键    if (key.charCodeAt(0) === 13) {      // 将行数据进行增加进去      if (currentLineData !== '') {      //将以后行数据传入历史命令数组中存储        historyLineData.push(currentLineData)          //定义以后行命令在整个数组中的地位        last = historyLineData.length - 1      }      //当输出clear时清空终端内容      if (currentLineData === 'clear') {        term.clear()      }    //在这能够进行发动申请将整行数据传入      // 清空以后行数据      currentLineData = ''      term.write(`\r\n${terminalTitleTemplate}: `)    } else if (key.charCodeAt(0) === 127) {      //删除键--》以后行偏移量x大于终端提示符所占地位时进行删除      if (term._core.buffer.x > terminalTitleTemplate.length + 1) {        currentLineData = currentLineData.slice(0, -1)        term.write('\b \b')      }    } else if (key === '\u001b[A') {      //up键的时候      let len = 0      if (historyLineData.length > 0) {        len = historyLineData.length + 1      }      if (last < len && last > 0) {          //以后行有数据的时候进行删除掉在进行渲染上存储的历史数据        for (let i = 0; i < currentLineData.length; i++) {          if (term._core.buffer.x > terminalTitleTemplate.length + 1) {            term.write('\b \b')          }        }        let text = historyLineData[last - 1]        term.write(text)          //重点,肯定要记住存储以后行命令保障下次up或down时不会光标错乱笼罩终端提示符        currentLineData = text        last--      }    } else if (key === '\u001b[B') {      //down键      let lent = 0      if (historyLineData.length > 0) {        lent = historyLineData.length - 1      }      if (last < lent && last > -1) {        for (let i = 0; i < currentLineData.length; i++) {          if (term._core.buffer.x > terminalTitleTemplate.length + 1) {            term.write('\b \b')          }        }        let text = historyLineData[last + 1]        term.write(text)        currentLineData = text        last++      }    } else {      //啥也不做的时候就间接输出      currentLineData += key      term.write(key)    }  })}

四.渲染执行

useEffect(() => {    //   创立实例    term.open(document.getElementById('ter'))    // 初始化    term._initialized = true    term.prompt()    // 进行适应容器元素大小    term.loadAddon(fitAddon)    fitAddon.fit()    term.focus()   keyAction()                  return () => {      term.dispose()    }  }, [])  return (    <>      {/* terminal装载容器 */}      <div id="ter" />    </>  )

结尾话外题,在写这个的时候就因为应用up/down键的时候光标串行且输入命令还串行了。就找了特地久,始终不明确。一开始用的onKey来监听键盘操作,onData来保障粘贴输出汉字。就真的间接错乱。前面发现间接onData监听输出就不会如此,不存在这个问题了