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" /> </> )