xterm.js 前端终端库(React)「建议收藏」

xterm.js 前端终端库(React)「建议收藏」xterm.js 的使用。需求: 打开控制台,弹出一个新的页面,页面显示终端,通过WebSocket与后端进行连接。

官网:xtermjs.org/

npm install xterm


需求:打开控制台,弹出一个新的页面,页面显示终端,通过WebSocket与后端进行连接。

1、打开一个特定的页面。

import React from 'react'; 
import Terminal from '@/components/Terminal';
// ... 
const redirectToTerminal = () => ( 
    <Router> <Route path="/terminal/:url" components={Terminal} exact /> </Router>
); 
if (window.location.href.includes('terminal')) {
    return redirectToTerminal();
};

2、终端适应父元素的大小

按照官网的描述,是使用 xterm-addon-fit插件。

npm install xterm-addon-fit

以及官网描述的使用方式

import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
const term = new Terminal();
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
// Open the terminal in #terminal-container 
term.open(document.getElementById('terminal-container'));
// Make the terminal's size and geometry fit the size of #terminal-container
fitAddon.fit();

后来又时间查看源码【源码】,返回了4个方法,分别是 activate(启动),dispose(销毁),fit(适应),proposeDimensions(获取尺寸)

3、终端进行websocket连接

官网也有一个插件可以使用 xterm-addon-attach

npm install xterm-addon-attach

以及官网描述的使用方式


import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
const term = new Terminal(); 
const socket = new WebSocket('wss://docker.example.com/containers/mycontainerid/attach/ws');
const attachAddon = new AttachAddon(socket);
// Attach the socket to term
term.loadAddon(attachAddon);

由于在自己使用时,在界面显示时出现了问题,后端返回的数据未经过处理在界面上显示了一次,然后处理过后的又显示了一次,就很尴尬。最后在代码中,我是没有使用的。

看了一下源码【源码】,总共也就两个方法,一个是 activate(启动),一个是dispose(销毁)在 activate 方法中 直接对返回的数据进行了初步的处理然后 terminal.write 了,我个人认为是这个原因导致的。

image.png


最后 Terminal.tsx 源码

import React, { useEffect } from 'react';
import 'xterm/css/xterm.css';
import { Terminal } from 'xterm';
import { useParams } from 'react-router';
import { AttachAddon } from 'xterm-addon-attach';
import { FitAddon } from 'xterm-addon-fit';
import cache from '@/utils/storage';
const TOKEN = 'token';
const action = (type: any, data?: any) => {
	const action = Object.assign(
		{
			type: type
		},
		data
	);
	return JSON.stringify(action);
};
interface ParamsProps {
	url: string;
}
export default function MidTerminal(): JSX.Element {
	const params: ParamsProps = useParams();
	// 添加https和http的支持
	// wss://${window.location.hostname}:${window.location.port}
	const socketUrl =
		window.location.protocol.toLowerCase() === 'https:'
			? `wss://x.x.x.x:xxxx/ws/terminal?${params.url}`
			: `ws://x.x.x.x:xxxx/ws/terminal?${params.url}`;
	useEffect(() => {
		const socket = new WebSocket(socketUrl, cache.getLocal(TOKEN));
		const terminal = new Terminal({
			cursorStyle: 'underline',
			cursorBlink: true,
			theme: {
				foreground: '#dddddd',
				cursor: 'gray'
			},
			windowsMode: true
		});

		const fitAddon = new FitAddon();
		terminal.loadAddon(fitAddon);
		const terminalDom = document.getElementById('terminal-container');
		terminal.open(terminalDom as HTMLElement);
		fitAddon.fit();
		socket.onopen = () => {
			socket.send(action('TERMINAL_INIT'));
			socket.send(action('TERMINAL_READY'));
			socket.send(
				action('TERMINAL_RESIZE', {
					columns: fitAddon.proposeDimensions().cols,
					rows: fitAddon.proposeDimensions().rows
				})
			);
			terminal.write('Welcome to terminal! \r\n$');
		};
		socket.onclose = () => {
			terminal.write('Bye Bye! \r\n$');
		};
		socket.onerror = () => {
			terminal.write('Something errors \r\n$');
		};
		terminal.onData((e: string) => {
			socket.send(
				action('TERMINAL_COMMAND', {
					command: e
				})
			);
		});
		socket.onmessage = (e: MessageEvent<any>) => {
			const data = JSON.parse(e?.data);
			if (data?.type == 'TERMINAL_PRINT') {
				terminal.write(data.text);
			}
		};
		return () => {
			socket.close();
			terminal.dispose();
		};
	}, []);

	return (
		<div id="terminal-container" style={{ width: '100%', height: '100%' }} ></div>
	);
}


xterm插件前前后后搞了近一个星期,看了源码还有很多插件没有使用过,这次也只是使用了最基础的两个,以后有机会的话会尝试一下其他的插件的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13546.html

(0)

相关推荐

发表回复

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