学习node+websocket+vue3搭建多人聊天室
跟着做小白都能做出来~~
首先搭建前端Vite 项目
兼容性注意
Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
使用 npm或yarn、pnpm任意安装,个人推荐pnpm,原因如下
- 快速:pnpm比传统方案(yarn, npm)安装包的速度快了两倍,甚至比yarn2,pnp模式还要快
- 更严格高效:node_modules 中的文件是从一个单一的可内容寻址的存储中链接过来的,代码无法访问任意包
- monorepo:天然内置支持当仓库多包
$ npm create vite@latest
$ yarn create vite
$ pnpm create vite
1.安装并输入项目名称
2.这里选择vue
3.根据个人选择,这里选择js
4.到这里就成功快速搭建完成vite3+vue3前端基础框架了,跟着下面的命令执行即可
在vsocde编辑器中打开
打开src目录,建立以下模块结构
首先cofigjs这里是用来统一管理地址的,后期维护也方便只需要修改地址即可
1.congfig-index.js中,这里写的是websokct
// 域名地址(项目实地址)这里写的是本地的地址
const BASE_URL='127.0.0.1'
// 端口号
const WS_PORT='8000'
// WebSocket协议的URL
export const WS_ADDRESS=`ws://${BASE_URL}:${WS_PORT}`
这里的hooks是vue3借鉴的react函数式组件的优点
2.hooks-index.js
// 这里的index.js文件用于统一引用导出hooks的方法。更规范
import useWebSocket from './websocket'
export { useWebSocket }
hooks-websocket.js
// 引用config-index.js封装好的WebSocket协议的URL
import { WS_ADDRESS } from "../configs"
// 封装一个使用websocket的高阶函数
// 这里的handleMessage用于接收及发送的消息
function useWebSocket(handleMessage) {
// 建立连接(创建WebSocket对象):
// const ws = new WebSocket(url, [protocol]);// url:服务器端地址;protocol:可选,指定可接受的子协议。
const ws = new WebSocket(WS_ADDRESS)
const init = () => {
bindEvent()
}
init()
function bindEvent() {
// ws.onopen():连接建立时触发的事件
ws.addEventListener('open', handleOpen, false);
// ws.onclose():关闭连接方法
ws.addEventListener('close', handleClose, false);
// ws.onerror():通信发生错误时触发
ws.addEventListener('error', handleError, false);
// ws.onmessage(): 客户端接收服务器端发送的信息时触发
ws.addEventListener('message', handleMessage, false);
}
function handleOpen(e) {
console.log('WebSocket open', e)
}
function handleClose(e) {
console.log('WebSocket close', e)
}
function handleError(e) {
console.log('WebSocket error', e)
}
return ws
}
export default useWebSocket
3.pages-home.vue建立简单的聊天页面
<script setup>
// onMounted:挂载完数据
// reactive:响应式数据,reactive 参数必须是对象 (json / arr)
// toRaw:响应式转化普通对象
// toRefs:降reactive中的响应式结构为一个个的ref响应式数据
import { onMounted, reactive, toRaw, toRefs } from "vue";
// 引用全局路由对象useRouter
import { useRouter } from "vue-router";
// 引用hooks中封装好的高阶函数,用于消息发送
import { useWebSocket } from '../hooks'
// 这里useWebSocket(handleMessage)用于接收消息
const ws = useWebSocket(handleMessage)
const router = useRouter()
// 定义state用于接收和发送的消息
const state = reactive({
msg: '',
msgList: []
})
// 结构state
const { msg, msgList } = toRefs(state)
// 获取用户名,没有就跳转到登录页
let username = ''
onMounted(() => {
username = localStorage.getItem('username')
if (!username) {
router.push('/login')
return
}
})
// 发送消息按钮
const sendMsg = () => {
if (msg.length < 1) {
return
}
// ws.send():发送信息的方法
// 由于后台接收的是JSON类型,这里发送的消息需要JSON.stringify
ws.send(JSON.stringify({
id: new Date().getTime(),
user: localStorage.getItem('username'),
dateTime: new Date().getTime(),
// 这里必须让msg失去响应式或深拷贝该值,否则造成发送的消息根据再次输入的消息发生变更
msg: toRaw(msg.value),
}))
// 发送完清空消息框
msg.value = ''
}
// 用于接收发送过来的消息
function handleMessage(e) {
// 由于后台接收的是JSON类型,这里发送的消息需要JSON.parse
const msgData = JSON.parse(e.data)
// 向列表添加每条聊天消息
msgList.value.push(msgData)
}
</script>
<template>
<div>
<ul>
<li v-for="item in msgList" :key="item.id">
<p>用户名:{{ item.user }}</p>
<p>{{ new Date(item.dateTime) }}</p>
<p>消息:{{ item.msg }}</p>
</li>
</ul>
<input type="text" placeholder="请输入消息" v-model="msg">
<button @click="sendMsg">发送</button>
</div>
</template>
<style scoped>
li p {
text-align: left;
}
</style>
pages-login.vue进入聊天室的页面
<template>
<div>
<input type="text" placeholder="请输入用户名" v-model="userName">
<button @click="enterSocket">进入聊天室</button>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import { useRouter} from 'vue-router'
const router=useRouter()
const userName=ref('')
onMounted(()=>{
userName.value=localStorage.getItem('username')
// 简单的判断是否已进入聊天室
if(userName.value){
router.push('/home')
return
}
})
// 进入聊天室
const enterSocket=()=>{
if(userName.value<6){
alert('用户名不小于6位')
return
}
localStorage.setItem('username',userName.value)
userName.value=''
router.push('/home')
}
</script>
4.router-index.js 由于框架是没有自带router的这里需要去pnpm i vue-router安装下
import { createRouter, createWebHashHistory } from "vue-router";
import routes from "./router";
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
router-router.js
import login from "../pages/login.vue";
// 路由列表
let routes= [
{
path: "/login",
name: "login",
component: login,
},
{
path: "/home",
name: "home",
component: () => import("../pages/home.vue"),
children: [],
},
];
export default routes;
5.App.vue
<template>
<router-view></router-view>
</template>
6.main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from "./router";
createApp(App).use(router).mount('#app')
6.在当前目录下新建server目录,用于node服务
进入server目录生成package.json
然后安装包
在安装websocket的插件wx
接着是node的目录如一下就完成
在package.json中配置启动命令如
index.js中写
// 使用CommonJS require引入
// CommonJS 中的 require/exports 和 ES6 中的 import/export 区别
// CommonJS 模块是运行时加载,ES6 Modules 是编译时加载并输出接口。
// CommonJS 输出是值的拷贝;ES6 Modules输出的是值的引用,被输出模块的内部的改变会影响引用的改变。
// CommonJs 导入的模块路径可以是一个表达式,因为它使用的是 require() 方法,甚至这个表达式计算出来的内容是错误的路径,也可以通过编译到执行阶段再出错;
// 而ES6 Modules 只能是字符串,并且路径不正确,编译阶段就会抛错。
// CommonJS this 指向当前模块,ES6 Modules this 指向 undefined
// ES6 Modules 中没有这些顶层变量:arguments、require、module、exports、__filename、__dirname
const Websocket=require('ws')
;((Ws)=>{
// 建立ws服务地址,这里跟前端都类似了唯一的区别是connection和message(连接和消息)
const server=new Ws.Server({port:8000,host:"0.0.0.0"})
const init=()=>{
bindEvent()
}
function bindEvent(){
server.on('open',function(event){
server.send('OpenBarScanner')
})
server.on('close',handelClose)
server.on('error',handelError)
server.on('connection',handelConnection)
}
function handelOpen(){
console.log('handelOpen')
}
function handelClose(){
console.log('handelClose')
}
function handelError(){
console.log('handelError')
}
// 连接时提示消息并发送到客户端
function handelConnection(ws){
console.log('WebSocket Connection')
ws.on('message',handelMessage)
}
// 用于接收发送的消息
function handelMessage(msg){
server.clients.forEach((c)=>{
// 由于node发送到客户端的消息是Blob类型,这里需要用Buffer.form().toString()转化为utf8类型识别消息
c.send(Buffer.from(msg).toString('utf8'))
})
}
init()
})(Websocket)
还没有评论,快来发表第一个评论吧