目标实现效果:
所需工具:
WebSSH在线编程工具介绍
首先我们需要 在页面的一个终端模拟器。
XTerm 就会解决这个,找到 vue 项目中的 package.json 文件
在Node.js中,模块是一个库或框架,也是一个Node.js项目。Node.js项目遵循模块化的架构,当我们创建了一个Node.js项目,意味着创建了一个模块,这个模块的描述文件,被称为 package.json。
打开
在 dependencies 下面填写 xterm 喝对应的版本号 我们这里用 3.1.0 的,然后删除 vue 的依赖包
删除后在执行 npm install 下载依赖、这里解释一下
dependencies:应用能够正常运行所依赖的包。用户在使用 npm install 安装你的包时会自动安装这些依赖。
详细版
创建 vue 页面
<template>
<div id="terminal">
</div>
</template>
<script>
import { Terminal } from 'xterm' // 初始化组件
import * as attach from 'xterm/lib/addons/attach/attach' // 给终端窗口绑定功能
import * as fit from 'xterm/lib/addons/fit/fit' // 窗口自适应
Terminal.applyAddon(attach) // 功能添加
Terminal.applyAddon(fit)
export default {
name: "console.vue",
mounted() {
var terminalContainer = document.getElementById('terminal')
this.term = new Terminal(this.terminal) // 初始化终端
this.term.open(terminalContainer) // 将 div 绑定到初始化后的终端
}
}
</script>
<style scoped>
</style>
创建 终端展示的 DIV、引入终端 和 必要的两个功能、将功能插件添加到终端组件。然后 定义 mounted 钩子, 获取到 div 标签的 id,将 id 帮定到实例化好的 终端组件上、你也可以理解是 终端组件打开了 div
// main.js
import 'xterm/dist/xterm.css'
import console from '@/components/console'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [{
path: '/console',
name: 'console',
component: console
}
]
})
打开 页面 就会看到 终端的 黑窗口了
下一步, 连接远程的 终端 Linux 也好 centos7 也好,这个时候我们要用到 WebSocket 进行连接 传递数据 到 Django。
还是在 mounted 下
// mounted
this.terminalSocket = new WebSocket('ws://127.0.0.1:8000/webssh/') // 初始化 WebSocket 指定好向后代发送的地址
this.term.attach(this.terminalSocket) // 将 终端 附属到 WebSocket
初始化 的这一行代码 非常关键
WebSocket 的特点就是服务端可以主动向客户端推送消息,客户端也可以主动向服务端发送消息,实现了真正的平等。
引入 WebSocket、设置连接的端口、然后运用 attach 函数 附属、第一步 连接就做好了,连接之后 ,要写 最坏的打算, 比如 用户直接吧浏览器关闭了 连接也要 对应的断开。
这时 我们用 Vue 生命周期中的 beforeDestroy 钩子 来实现
想多了解的 vue生命周期钩子
// 和 mounted 同级
beforeDestroy() {
this.terminalSocket.close() // 关闭 WebSocket
this.term.destroy() // 关闭终端
}
beforeDestroy(对象准备死掉)
就在Vue对象被破坏并从内存中释放之前, deforeDestroy 钩子被触发
此时,就代表着 Vue页面上的终端 发送 WebSocket 给 Django了, 再写一个路由 接收(此时 前后端的跨域都是解决好的)
from django.urls import path, include
from online import views # online 是我的子应用
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('online.urls')),
path('webssh/', views.WebSSH.as_view())
# 因为要实现的不是一个接口 视图响应的功能 所以 不写 as_view() 也是可以的
]
全部代码
<template>
<div id="terminal">
</div>
</template>
<script>
import { Terminal } from 'xterm' // 初始化组件
import * as attach from 'xterm/lib/addons/attach/attach' // 给终端窗口绑定功能
import * as fit from 'xterm/lib/addons/fit/fit' // 窗口自适应
Terminal.applyAddon(attach) // 功能添加
Terminal.applyAddon(fit)
export default {
name: "console.vue",
mounted() {
var terminalContainer = document.getElementById('terminal')
this.term = new Terminal(this.terminal) // 初始化终端
this.term.open(terminalContainer) // 将 div 绑定到初始化后的终端
this.terminalSocket = new WebSocket('ws://127.0.0.1:8000/webssh/') // 初始化 WebSocket
this.term.attach(this.terminalSocket) // 将 终端 附属到 WebSocket
},
beforeDestroy() {
this.terminalSocket.close()
this.term.destroy()
// beforeDestroy(对象准备死掉)
// 就在Vue对象被破坏并从内存中释放之前, beforeDestroy 钩子被触发
}
}
</script>
<style scoped>
</style>
此时 前台 Vue 已经发送过来了 WebSocket, 后台 Django 接收 需要用到 dwebsocket
pip install dwebsocket
下载好之后 注册到 Django settings 的 INSTALLED_APPS里
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'online',
'rest_framework',
# 'corsheaders',
'djcelery',
'dwebsocket' # 在这里
]
dwebsocket 提供了一个装饰器 @accept_websocket、它装饰的视图函数只会接收到 WebSocket 的请求 隔离了其他无用的 HTTP 链接。
# views.py
from dwebsocket import accept_websocket # 引入
@accept_websocket # 只接受 WebSocket 的 请求
def WebSSH(request):
if request.is_websocket:
pass
前台的 WebSocket 已经完全连接上 后台的 dwebsocket 了
就先这样先把视图模子写好,下一章 实现 页面操作 对应的 处理