在前端领域 ,实时通信 WebSocket 是我们必须掌握的其中一个技术点 ,今天木鱼和大家通过案例,快速的入门WebSocket 实时通信 。一🏍 届时我将代码部分,按照先后顺序,给大家通过文章的形式去分析。
木鱼也是刚刚开始了解WebSocket ,如有不对的地方,请谅解。留言区,时刻恭候大家,我们共同迈进通信工程。
为了方便大家学习,本文只展示UI组件库 、逻辑部分 | 样式部分 不做展示 小伙伴们可以去 👉案例源码 获取。
1、什么是WebSocket?
根据百科给出的解释是:
- WebSocket是一种在
单个TCP连接上 进行全双工通信 的协议。 - WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。
- WebSocket API也被
W3C定为标准 。 - WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
其实一句话就可以做出概括:它就是一种网络通信协议 ,很多高级功能都需要它。
2、为什么需要 WebSocket?
初次接触 WebSocket 的人,都会问想一个问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它到底能带来什么好处?
答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。
比如说:我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。
3、特点
服务器 可以主动向客户端推送信息 ,客户端 也可以主动向服务器发送信息 ,是真正的双向平等对话,属于服务器推送技术的一种。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
4、vue2案例
(1) 技术栈
- vue-cli@3.12.1
- Ant Design of Vue
- vue-router
- localStorage
- moment
- ws
首先我们使用的是 Ant Design of Vue 样式组件库
①安装 ant-design-vue
npm i --save ant-design-vue
②在main.js中 完整引入
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
Vue.use(Antd);
(2) 目录结构
(3)router.js配置
import Vue from 'vue'
import Router from 'vue-router'
import Login from './views/Login.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/',
name: 'Home',
component: () => import( './views/Home.vue')
}
]
})
(4) 登录 【Login.vue】
一💕登录布局:
在布局前,我们先构思好页面分布,良好的开端,要占据开发的一半。有思路,才会事半功倍。
- 聊天室标题
- 用户名输入框
- 进入聊天室按钮
- 背景界面圆角 【样式处理】
①聊天室标题
<div class="boxs">
<h1>木鱼全球·畅聊</h1>
</div>
②用户名输入框
<a-input placeholder="请您输入用户名">
<a-icon slot="prefix" type="user" style="color: rgba(0, 0, 0, 0.25)"/>
</a-input>
③进入聊天室按钮
<a-button type="dashed" ghost>
<i class="iconfont icon-SEND" @click="添加进入聊天室事件👇"></i>进入聊天室
</a-button>
如何自定义图标请参考 👉如何引用阿里图标库
一💕登录逻辑:
①用户输入信息:在输入框 内绑定 v-model="username"
在data 中定义存储用户信息的桶
data() {
return {
username: "",
};
},
②进入聊天室事件:@click="handleEnterBtnClick"
handleEnterBtnClick() {
const username = this.username.trim();
if (username.length < 3) {
this.$message.warning("用户名不能小于3位", 1);
return;
}
localStorage.setItem("username", username);
this.$router.push("/");
},
③针对于 本地里有或者没有用户名信息
如果有 进入首页聊天室,否则 返回登录页【首页返回的操作】
mounted() {
const username = localStorage.getItem("username");
if (username) {
this.$router.push("/");
return;
}
},
④清除本地存储当中的信息【演示效果】
(5) 首页【Home.vue】
一💕首页布局:
①消息列表:
<a-list ref="record" item-layout="horizontal" :data-source="msgList">
<a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta>
<p slot="title">
<span> {{ item.user }}</span>
<span>发送时间:{{ $moment(item.dateTime).format("YYYY-MM-DD HH:mm:ss") }}</span>
</p>
<p slot="title">会话内容:{{ item.msg }}</p>
<a-avatar slot="avatar" src="https://gw.alicdn.com/tps/TB1W_X6OXXXXXcZXVXXXXXXXXXX-400-400.png"/>
</a-list-item-meta>
</a-list-item>
</a-list>
附加:关于遍历的时间格式处理 请看:vue时间格式处理(YYYY-MM-DD HH:mm:ss)
②内容输入框:
<a-input placeholder="请输入消息"/>
③发送按钮:
<a-button type="dashed" ghost>
<i class="iconfont icon-SEND"></i>
发送
</a-button>
一💕首页逻辑【WebSocket默认配置】:
首先建立WebSocket 连接,我们要知道 WebSocket 在前端工程 支持 4种属性一👇
- open 【建立连接】
- close 【关闭连接】
- error 【错误信息】
- message 【接收处理】
附加了解内容:一🍾
后端的WebSocket 支持五种:
- open 【建立连接】
- close 【关闭连接】
- error 【错误信息】
- message 【连接处理】
- connection 【信息处理函数】
在外部作用域调用: 详细WebSocket 服务链接部署 ,请看下面 (6) node 通信部署 一🎈
const ws = new WebSocket("ws://localhost:8000");
此时需要vue2 项目位置–》下载ws
npm install ws -g
①建立连接:
在mounted 生命周期内,写出 WebSocket 连接结构代码【以下属于原生写法】
注意:
this.handleWsOpen 【作用于调用 methods中的连接函数事件】bind(this) 【bind(this)的作用是改变this的指向】
②默认配置:
mounted() {
ws.addEventListener("open", this.handleWsOpen.bind(this), false);
ws.addEventListener("close", this.handleWsClose.bind(this), false);
ws.addEventListener("error", this.handleWsError.bind(this), false);
ws.addEventListener("message", this.handleWsMessage.bind(this), false);
},
③配置连接参数:
在methods 生命周期内 配置,它的默认参数
methods: {}
handleWsOpen(e) {
console.log("FE:WebSocket open", e);
},
handleWsClose(e) {
console.log("FE:WebSocket close", e);
},
handleWsError(e) {
console.log("FE:WebSocket error", e);
},
这步很重要,作用于前端接收广播数据 一🎯
handleWsMessage(e) {
console.log("FE:WebSocket message", e);
},
④刷新处理函数事件:
我们需要在mounted 生命周期 中 添加 刷新页面处理函数
判断本地存储当中有没有用户名,如果有用户名 点击浏览器刷新【F5】,不做跳转,否则跳转至登录页
mounted(){
this.username = localStorage.getItem("username");
if (!this.username) {
this.$router.push("/Login");
return;
}
}
(6) node通信部署
一💕初始化处理
注意:在部署前,首先必须要做初始化处理
在server 目录下 运行 npm init -y 初始化
npm init -y
一💕监听处理
使用nodemon 插件 做监听处理函数 一👆 也是在server 目录下运行
npm install nodemon -g
一💕启用监听
在package.json 文件中修改 scripts 内的参数
- dev 【运行方式,通过npm run dev】
- nodemon index.js 【使用监听nodemon】、【引用index.js 文件】
"scripts": {
"dev": "nodemon index.js"
},
一💕下载 ws 库【 附属于 WebSocket】
一👆 也是在server 目录下运行
npm install ws
一💕新建index.js
①导入const Ws = require('ws');
const Ws = require('ws');
;((Ws) => {
})(Ws)
②主要WebSocket配置【主要代码】
const server = new Ws.Server({
port: 8000
});
const init = () => {
bindEvent()
}
function bindEvent() {
server.on('open', handleOpen)
server.on('close', handleClose)
server.on('error', handleError)
server.on('connection', handleConnection)
}
function handleOpen() {
console.log('BE:WebSocket open');
}
function handleClose() {
console.log('BE:WebSocket close');
}
function handleError() {
console.log('BE:WebSocket error');
}
function handleConnection(ws) {
console.log('BE:WebSocket connection');
ws.on('message', handleMessage)
}
function handleMessage(msg) {
server.clients.forEach((c) => {
c.send(msg);
})
}
(7) 首页添加触发事件函数
① 请输入消息框 绑定 v-model="msg"
<a-input placeholder="请输入消息" v-model="msg"/>
data() {
return {
msg: "",
username: "",
msgList: [],
};
},
②发送按钮绑定事件 @click="handleSendBtnClick"
<a-button type="dashed" ghost @click="handleSendBtnClick">
<i class="iconfont icon-SEND"></i>发送
</a-button>
handleSendBtnClick(e) {
if (this.msg == "") {
this.$message.warning("不能发送空白消息", 1);
} else {
const msg = this.msg;
if (!msg.trim().length) {
return;
}
ws.send(
JSON.stringify({
id: new Date().getTime(),
user: this.username,
dateTime: new Date().getTime(),
msg: this.msg,
})
);
this.msg = "";
}
},
③ 接收广播数据
在methods 中增加handleWsMessage 处理函数 接收返回的数据
handleWsMessage(e) {
const msg = JSON.parse(e.data);
this.msgList.push(msg);
console.log(msg);
},
(8) 通信演示
结束:一个简单的WebSocket 案例 已完成。
如果有不明白的地方,小伙伴们可以在评论区留言 。
|