vue + socket.io實(shí)現(xiàn)一個(gè)簡(jiǎn)易聊天室示例代碼
vue + vuex + elementUi + socket.io實(shí)現(xiàn)一個(gè)簡(jiǎn)易的在線(xiàn)聊天室,提高自己在對(duì)vue系列在項(xiàng)目中應(yīng)用的深度。因?yàn)閷W(xué)會(huì)一個(gè)庫(kù)或者框架容易,但要結(jié)合項(xiàng)目使用一個(gè)庫(kù)或框架就不是那么容易了。功能雖然不多,但還是有收獲。設(shè)計(jì)和實(shí)現(xiàn)思路較為拙劣,懇請(qǐng)各位道友指正。
可以達(dá)到的需求
- 能查看在線(xiàn)用戶(hù)列表
- 能發(fā)送和接受消息
使用到的框架和庫(kù)
- socket.io做為實(shí)時(shí)通訊基礎(chǔ)
- vuex/vue:客戶(hù)端Ui層使用
- Element-ui:客戶(hù)端Ui組件
類(lèi)文件關(guān)系圖
服務(wù)端:

客戶(hù)端:

服務(wù)端實(shí)現(xiàn)
實(shí)現(xiàn)聊天服務(wù)器的相關(guān)功能,包含通訊管道的創(chuàng)建、用戶(hù)加入、消息的接受與轉(zhuǎn)發(fā)等。
一、通訊服務(wù)建立
build/server-config.js:聊天服務(wù)器的入口
let socketIo = require('socket.io');
let express = require('express');
let cxt = require('../src/services-server');
let httpPort = 9001;
let channelId = 1
let app = express();
app.get('/',function(req,res){
res.send('啟動(dòng)成功:' + httpPort);
});
let server = require('http').createServer(app);
let io = socketIo(server);
io.on('connection',function(socket){
console.log('有客戶(hù)端連接');
cxt.createChannel(channelId++,socket)
});
server.listen(httpPort); //用server連接
console.log('io listen success !! ' + httpPort);
- 通過(guò)express創(chuàng)建一個(gè)server對(duì)象,然后利用socketIo創(chuàng)建io對(duì)象
- 然后通過(guò)io的on方法監(jiān)聽(tīng)connection事件
- 當(dāng)有客戶(hù)端連接時(shí),觸發(fā)connection事件,縣立即調(diào)用"服務(wù)端上下文(后面簡(jiǎn)稱(chēng)cxt)"的createChannel方法創(chuàng)建一個(gè)管道,此時(shí)的管道上是沒(méi)有用戶(hù)信息的。
二、創(chuàng)建上下文(服務(wù)端上下文)
實(shí)現(xiàn)一個(gè)聊天室上下文,包含:用戶(hù)、房間、消息、管道等數(shù)組,所以代碼都在service-server目錄中。
- index.js:聊天室服務(wù)端上下文創(chuàng)建入口,創(chuàng)建context,并初始化房間到上下文中。
- context.js:聊天室服務(wù)端上下文類(lèi),用戶(hù)、房間、消息、管道等類(lèi)在此中做集中管理。
- room目錄:包含房間和房間集合的實(shí)現(xiàn)
- channel:服務(wù)端與客戶(hù)端通訊的管道類(lèi)
結(jié)合"通訊服務(wù)建立"中的connectiong事件的觸,其后轉(zhuǎn)到cxt.createChannel方法
createChannel (id, socket) {
let channel = new Channel(id, socket, this)
channel.init()
channel.index = this.channels.length
this.channels.push(channel)
}
此時(shí)會(huì)創(chuàng)建一個(gè)管道實(shí)例,然后初始化管道實(shí)例,并將管道添加到管道數(shù)組中。以下是初始化管道實(shí)例的代碼:
init () {
let self = this
let roomInfo = this.cxt.room.collections[0]
this.roomInfo = roomInfo
this.socket.join('roomId' + roomInfo.id)
this.socket.emit(this.cxt.eventKeys.emit.sendRooms, roomInfo) /* send出去一個(gè)默認(rèn)的房間 */
this.socket.on(this.cxt.eventKeys.client.registerUser, function (id, name) {
console.log(id + '-' + name + '--' + self.id)
self.cxt.createUserById(id, name, self.id)
}) /** 新用戶(hù)注冊(cè) */
this.socket.on(this.cxt.eventKeys.client.newMsg, function (msg) { /** 發(fā)送消息 */
self.notifyMsg(msg)
console.log(msg)
self.cxt.addMsg(msg)
})
this.socket.on(this.cxt.eventKeys.client.closeConn, function () {
console.log(self.id + '--關(guān)閉連接')
self.cxt.remove(self)
})
this.sendUsers()
}
在初始化管道實(shí)例時(shí)做了如下事件:
- 將通訊socket添加一個(gè)到房間中,方便后期好廣播消息
- 向當(dāng)前連接上來(lái)的socket發(fā)送房間信息,設(shè)定為第一個(gè)房間
- 監(jiān)聽(tīng)三個(gè)事件:用戶(hù)注冊(cè)、新消息、關(guān)閉連接。此處都要邏輯處理,可以參考源碼。
客戶(hù)端實(shí)現(xiàn)
主要實(shí)現(xiàn)連接服務(wù)、注冊(cè)用戶(hù)、發(fā)送和接受消息的功能。首先以main.js為入口,且需要先裝配好vue相關(guān)配件,如vuex、ElemUi、客戶(hù)端通訊管道等,然后創(chuàng)建vue實(shí)例和連接消息服務(wù)器,代碼如下:
import '../node_modules/bootstrap/dist/css/bootstrap.css'
import Vue from 'vue'
import ElemUi from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import App from './App'
import * as stores from './store'
import { Keys } from './uitls'
import { getCxt } from './services-client'
let initRoomInfo = Keys.SETROOMINFO
Vue.use(ElemUi)
/* eslint-disable no-new */
new Vue({
store: stores.default,
el: '#app',
template: '<App/>',
components: { App },
created: function () {
let self = this
getCxt().createIo(this, function (roomInfo) {
stores.busCxt.init() /** 初始化view與service層的交互層(業(yè)務(wù)層) */
self.$store.dispatch(initRoomInfo, roomInfo)
getCxt().refUsers(function (users) {
stores.busCxt.userCxt.refUsers(users)
})
})
}
})
一、與服務(wù)端的通訊
service-client目錄中實(shí)例的與消息服務(wù)器通訊,其中包含創(chuàng)建用戶(hù)、接受和發(fā)送消息等。一個(gè)客戶(hù)端只能擁有一個(gè)消息管道,以下代碼是消息管理的創(chuàng)建:
import * as io from 'socket.io-client'
import Context from './context'
let eventKeys = require('../services-uitls/event.keys')
let url = 'http://localhost:9001/'
let cxt = null
export function getCxt () {
if (cxt == null) {
cxt = new Context(url, eventKeys, io)
}
return cxt
}
在main.js中的vue實(shí)例的created勾子中調(diào)用了Context的createIo實(shí)例方法,用于創(chuàng)建一個(gè)與消息服務(wù)器的連接,并接受其中房間發(fā)送回來(lái)的房間信息。然后就初始化業(yè)務(wù)層。
二、vuex的結(jié)合
在store目錄中實(shí)現(xiàn),包含了vuex類(lèi)相關(guān)的實(shí)現(xiàn),還有業(yè)務(wù)層的實(shí)現(xiàn)。其中業(yè)務(wù)層會(huì)引用"客戶(hù)端通訊管道",而vuex實(shí)現(xiàn)類(lèi)有可能會(huì)引用業(yè)務(wù)層相關(guān)實(shí)現(xiàn)類(lèi),以此實(shí)現(xiàn)ui到"消息服務(wù)器"的通訊。 store/index.js代碼如下:
import Vuex from 'vuex'
import Vue from 'vue'
import RoomViewCxt from './room/roomViewCxt'
import UserViexCxt from './userViewCxt'
import MsgViewCxt from './msg/msgViewCxt'
import BusCxt from './indexForBus'
let _busCxt = new BusCxt()
let _rvCxt = new RoomViewCxt()
let _uvCxt = new UserViexCxt(_busCxt.userCxt)
let _mvCxt = new MsgViewCxt()
let opt = {
state: null,
getters: null,
mutations: null,
actions: null
}
_rvCxt.use(opt)
_uvCxt.use(opt)
_mvCxt.use(opt)
Vue.use(Vuex)
let store = new Vuex.Store(opt)
export default store
export const busCxt = _busCxt /** 業(yè)務(wù)處理上下文 */
export function getBusCxt () {
return _busCxt
}
三、組件
組件只實(shí)現(xiàn)了 用戶(hù)注冊(cè)、主界面容器、消息發(fā)送和消息接受等。組件只會(huì)引用store目錄中相關(guān)類(lèi),不會(huì)直接引用管道類(lèi)。
- Login.vue:用戶(hù)注冊(cè)組件
- HChat.vue:主界面容器組件
- Message/MsgWriter.vue:發(fā)送消息組件
- Message/MsgList.vue:接受和顯示消息列表組件
如何運(yùn)行實(shí)例
- cnpm run install 安裝所有的依賴(lài)
- npm run sokcetIo 啟動(dòng)消息服務(wù)器
- npm run dev 啟動(dòng)客戶(hù)端
示例截圖

下載地址:vue-Socket_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
深入探究Vue中$nextTick的實(shí)現(xiàn)原理
這篇文章主要為大家詳細(xì)介紹Vue中$nextTick的實(shí)現(xiàn)原理,文中的示例代碼講解詳細(xì),對(duì)我們深入了解Vue有一定的幫助,需要的小伙伴可以參考一下2023-06-06
Vue頁(yè)面加載完成后如何自動(dòng)加載自定義函數(shù)
這篇文章主要介紹了Vue頁(yè)面加載完成后如何自動(dòng)加載自定義函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Vue3項(xiàng)目剛創(chuàng)建就報(bào)錯(cuò)的問(wèn)題及解決
這篇文章主要介紹了Vue3項(xiàng)目剛創(chuàng)建就報(bào)錯(cuò)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
解決vue中使用proxy配置不同端口和ip接口問(wèn)題
這篇文章主要介紹了解決vue中使用proxy配置不同端口和ip接口問(wèn)題 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
spring-cloud-stream的手動(dòng)消息確認(rèn)問(wèn)題
這篇文章主要介紹了spring-cloud-stream的手動(dòng)消息確認(rèn)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
VuePress在build打包時(shí)window?document?is?not?defined問(wèn)題解決
這篇文章主要為大家介紹了VuePress在build打包時(shí)window?document?is?not?defined問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Vue3配置vite.config.js解決跨域問(wèn)題的方法
跨域一般出現(xiàn)在開(kāi)發(fā)階段,由于線(xiàn)上環(huán)境前端代碼被打包成了靜態(tài)資源,因而不會(huì)出現(xiàn)跨域問(wèn)題,這篇文章主要給大家介紹了關(guān)于Vue3配置vite.config.js解決跨域問(wèn)題的相關(guān)資料,需要的朋友可以參考下2024-07-07

