需求:用vue、xtrerm、sockJS实现一个终端;
实现效果如下:
实现难点:主要是与服务端建立连接,后端用的sockJS前端保持一致,其实xterm中自带了websocket;视图展示用的xterm;
xterm.js官方文档
sockjs-client
主要代码逻辑:
<template>
<div id="term" class="term"></div>
</template>
<script>
import 'xterm/css/xterm.css'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import SockJS from 'sockjs-client'
mounted() {
this.initSocket()
},
methods: {
initSocket() {
//连接路径
if (this.socketURL == '') {
return
}
this.socket = new SockJS(this.socketURL)
this.socketOnOpen()
this.socketOnMessage()
this.socketOnClose()
this.socketOnError()
},
socketOnOpen() {
this.socket.onopen = () => {
console.log('web链接成功')
//发送格式与后台保持一致要不发送也是失败的
this.socket.send(
JSON.stringify({
Op: 'bind',
})
)
this.initTerm()
}
},
initTerm() {
this.term = new Terminal({
rendererType: 'canvas', //渲染类型
disableStdin: false, //是否应禁用输入
windowsMode: true, //根据窗口换行
cursorBlink: true, //光标闪烁
cursorStyle: 'underline', //光标样式
theme: {
foreground: '#ececec', //字体
background: '#000', //背景色
lineHeight: 16
}
})
let element = document.getElementById('term')
this.term.open(element)
const fitAddon = new FitAddon() //全屏插件
this.term.loadAddon(fitAddon)
//自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸)
this.fitAddon = fitAddon
this.fitAddon.fit()
this.term.focus()
this.term.onData(data => {
let dataMessage = data
//将输入的命令通知给后台,后台返回数据
if (data === '\r') {
data = '\n'
} else if (data === '\u0003') {
// 输入ctrl+c
data += '\n'
}
this.socket.send(
JSON.stringify({
Op: 'stdin',
Data: dataMessage,
Cols: this.term.cols || 30,
Rows: this.term.rows || 20
})
)
})
//接受服务器返回的结果并将结果显示到term中
socketOnMessage() {
this.socket.onmessage = evt => {
this.term.write(JSON.parse(evt.data).Data)
}
},
socketOnClose() {
this.socket.onclose = () => {
this.socket.close()
console.log('关闭 socket')
}
},
socketOnError() {
this.socket.onerror = () => {
console.log('socket 链接失败')
}
},
}
</script>
开发过程中遇到的痛点就是调试时很麻烦;后来后台将项目打包之后我本地起服务才能写单独的html页面去进行调试的但是和项目还是有出入;
这样比 打包到uat上去查问题方便一点 但是已经不是什么好的解决方案 调试的时候真的是有点烦躁~~