vue+xterm.js+websocket实现的网页版终端权威指南

引言

        因为最近项目需要写一个网页版终端,然而网上资料很多,但发现相关配置和API都很少,而且官网文档也很难看懂,因此小编翻阅了核心的源码,实现了一版,在此分享给各位码农。本篇文章将尽可能全面的罗列出xterm的配置和API。

1. 环境搭建

本文将针对如下版本的依赖进行说明:

"xterm": "^5.3.0",

"xterm-addon-fit": "^0.8.0"

2. 初始化xterm.js

<template>
    <div class="terminalPage">
        <div class="terminal" ref="terminalDiv"></div>
    </div>
</template>

<script>
import * as xterm from 'xterm';
import 'xterm/css/xterm.css';
import { FitAddon } from 'xterm-addon-fit'; // 横向自适应

export default {
    name: 'terminal',
    data() {
        return {
            xterm: null,
            fitAddon: null,
            ws: null,
            commandBuffer: ''
        }
    },
    mounted() {
        this.initTerminal();
    },
    methods: {
        initTerminal() {
            this.xterm = new xterm.Terminal({
                rows: 30, // 可视窗口的行数
                cols: 80, // 可是窗口的列数
                cursorBlink: true, // 光标是否闪烁
                // 终端主题
                theme: {
                    foreground: '#ffffff',
                    background: '#000000'
                    cursor: '#ffffff',
                },
                fontFamily: 'Consolas, Courier, monospace',
                fontSize: 14,

            });
            this.xterm.open(this.$refs.terminalDiv);
            this.fitAddon = new FitAddon();
            this.xterm.loadAddon(this.fitAddon);
            this.fitAddon.fit();
            window.addEventListener('resize', () => {
                try {
                    this.fitAddon.fit();
                } catch (e) {
                    this.$message.error(e.message);
                }
            });

            this.xterm.write('Connecting \r\n');
            this.xterm.onData((data) => this.terminalOnData(data));
            this.xterm.onKey((event) => this.terminalOnKey(event));
        },
    }
}

</script>

3. 使用onData监听输入并在终端中实时显示

methods: {

    terminalOnData(data) {
         this.term.write(data);
         this.commandBuffer += data;
    }
}

4. 使用onKey处理键盘的快捷键操作

methods: {

    terminalOnKey(event) {
        const { domEvent } = event;
        const ctrlKey = this.checkCtrlKeyAllSystem(domEvent); // 是否按了Ctrl键

        // 回车键
        if (event.domEvent.key === 'Enter') {
            // 发送命令
            this.ws.send(this.commandBuffer);
            this.commandBuffer = '';

        // Tab键
        } else if (event.domEvent.key === 'Tab') {
             // tab补全...
        }

        // Backspace退格键或Delete删除键
        } else if (event.domEvent.key === 'Backspace' || event.domEvent.key === 'Delete') {
             // 在终端中模拟删除效果
             this.xterm.write('\b \b');

        // 上箭头
        } else if (event.domEvent.key === 'ArrowUp') {
             // 历史指令...
        }

        // 下箭头
        } else if (event.domEvent.key === 'ArrowDown') {
             // 历史指令...

        // Ctrl+C 快捷键
        } else if (ctrlKey && event.domEvent.key === 'c') {
             // ...
        }

        // Ctrl+Shift+A 快捷键
        } else if (ctrlKey && domEvent.shiftKey && event.domEvent.key === 'a') {
             // ...
        }

        // 其他按键与快捷键等处理...  
        // ...      

        } else {
             this.term.write(key)
        }
    }

    // 判断是否按了Ctrl键 - 兼容Mac和Win不同系统
    checkCtrlKeyAllSystem(domEvent) {
        const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
        const isPressCtrlKey = isMac ? domEvent.metaKey : domEvent.ctrlKey;
        return isPressCtrlKey;
    },
}

5. 使用WebSocket连接至服务器

mounted() {
    this.initSocket();
},

methods: {
    initSocket() {
      this.ws = new WebSocket('ws://192.168.1.1:8080/websocket/terminal')
      this.ws.onopen = this.socketOnOpen;
      this.ws.onmessage = this.socketOnMessage;
      this.ws.onclose = this.socketOnClose;
      this.ws.onerror = this.socketOnError;
    },

    socketOnOpen() {
       this.xterm.write('连接成功');
    },

    socketOnMessage(event) {
        console.log('收到消息
要在 Vue 中使用 xterm.jsWebSocket 实现终端,你需要将用户输入的命令发送给后端,然后将后端返回的结果输出到 xterm.js 终端中。以下是一个简单的示例: ```html <template> <div id="terminal"></div> </template> <script> import { Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; export default { data() { return { socket: null, // WebSocket 实例 term: null, // Terminal 实例 }; }, mounted() { // 创建 WebSocket 实例 this.socket = new WebSocket('ws://localhost:8080'); // 创建 Terminal 实例 this.term = new Terminal(); const fitAddon = new FitAddon(); this.term.loadAddon(fitAddon); this.term.open(document.getElementById('terminal')); // 处理 WebSocket 消息 this.socket.onmessage = (event) => { this.term.write(event.data); }; // 处理输入事件 this.term.onData(data => { this.socket.send(data); }); // 调整终端大小 this.term.onResize(size => { const cols = size.cols; const rows = size.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }); // 发送 resize 消息 const cols = this.term.cols; const rows = this.term.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }, beforeDestroy() { // 关闭 WebSocket 连接 this.socket.close(); } } </script> ``` 以上代码中,我们首先在 `mounted` 钩子函数中创建了一个 WebSocket 实例和一个 Terminal 实例。然后我们为 WebSocket 实例添加了一个 `onmessage` 事件监听器,该监听器会在接收到服务器返回的消息时触发,我们在该事件处理函数中将消息输出到终端中。 接着,我们为 Terminal 实例添加了一个 `onData` 事件监听器,该监听器会在用户输入时触发,我们在该事件处理函数中向服务器发送用户输入的命令。同时,我们还为 Terminal 实例添加了一个 `onResize` 事件监听器,该监听器会在终端大小调整时触发,我们在该事件处理函数中向服务器发送终端大小变化的消息。 最后,我们在 `beforeDestroy` 钩子函数中关闭了 WebSocket 连接。 需要注意的是,以上代码中的 WebSocket 连接是通过 `ws://localhost:8080` 连接本地服务器的,你需要根据实际情况修改 WebSocket 连接地址。另外,代码中的消息格式和处理逻辑也需要根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妍思码匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值