vue + vuex + elementUi + socket.io實現一個簡易的在線聊天室,提高自己在對vue系列在項目中應用的深度。因為學會一個庫或者框架容易,但要結合項目使用一個庫或框架就不是那么容易了。功能雖然不多,但還是有收獲。設計和實現思路較為拙劣,懇請各位道友指正。
可以達到的需求
- 能查看在線用戶列表
- 能發送和接受消息
使用到的框架和庫
- socket.io做為實時通訊基礎
- vuex/vue:客戶端Ui層使用
- Element-ui:客戶端Ui組件
類文件關系圖
服務端:

客戶端:

服務端實現
實現聊天服務器的相關功能,包含通訊管道的創建、用戶加入、消息的接受與轉發等。
一、通訊服務建立
build/server-config.js:聊天服務器的入口
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('啟動成功:' + httpPort);
});
let server = require('http').createServer(app);
let io = socketIo(server);
io.on('connection',function(socket){
console.log('有客戶端連接');
cxt.createChannel(channelId++,socket)
});
server.listen(httpPort); //用server連接
console.log('io listen success !! ' + httpPort);
- 通過express創建一個server對象,然后利用socketIo創建io對象
- 然后通過io的on方法監聽connection事件
- 當有客戶端連接時,觸發connection事件,縣立即調用"服務端上下文(后面簡稱cxt)"的createChannel方法創建一個管道,此時的管道上是沒有用戶信息的。
二、創建上下文(服務端上下文)
實現一個聊天室上下文,包含:用戶、房間、消息、管道等數組,所以代碼都在service-server目錄中。
- index.js:聊天室服務端上下文創建入口,創建context,並初始化房間到上下文中。
- context.js:聊天室服務端上下文類,用戶、房間、消息、管道等類在此中做集中管理。
- room目錄:包含房間和房間集合的實現
- channel:服務端與客戶端通訊的管道類
結合"通訊服務建立"中的connectiong事件的觸,其后轉到cxt.createChannel方法
createChannel (id, socket) { let channel = new Channel(id, socket, this) channel.init() channel.index = this.channels.length this.channels.push(channel) }
此時會創建一個管道實例,然后初始化管道實例,並將管道添加到管道數組中。以下是初始化管道實例的代碼:
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出去一個默認的房間 */ this.socket.on(this.cxt.eventKeys.client.registerUser, function (id, name) { console.log(id + '-' + name + '--' + self.id) self.cxt.createUserById(id, name, self.id) }) /** 新用戶注冊 */ this.socket.on(this.cxt.eventKeys.client.newMsg, function (msg) { /** 發送消息 */ self.notifyMsg(msg) console.log(msg) self.cxt.addMsg(msg) }) this.socket.on(this.cxt.eventKeys.client.closeConn, function () { console.log(self.id + '--關閉連接') self.cxt.remove(self) }) this.sendUsers() }
在初始化管道實例時做了如下事件:
- 將通訊socket添加一個到房間中,方便后期好廣播消息
- 向當前連接上來的socket發送房間信息,設定為第一個房間
- 監聽三個事件:用戶注冊、新消息、關閉連接。此處都要邏輯處理,可以參考源碼。
客戶端實現
主要實現連接服務、注冊用戶、發送和接受消息的功能。首先以main.js為入口,且需要先裝配好vue相關配件,如vuex、ElemUi、客戶端通訊管道等,然后創建vue實例和連接消息服務器,代碼如下:
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層的交互層(業務層) */ self.$store.dispatch(initRoomInfo, roomInfo) getCxt().refUsers(function (users) { stores.busCxt.userCxt.refUsers(users) }) }) } })
一、與服務端的通訊
service-client目錄中實例的與消息服務器通訊,其中包含創建用戶、接受和發送消息等。一個客戶端只能擁有一個消息管道,以下代碼是消息管理的創建:
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實例的created勾子中調用了Context的createIo實例方法,用於創建一個與消息服務器的連接,並接受其中房間發送回來的房間信息。然后就初始化業務層。
二、vuex的結合
在store目錄中實現,包含了vuex類相關的實現,還有業務層的實現。其中業務層會引用"客戶端通訊管道",而vuex實現類有可能會引用業務層相關實現類,以此實現ui到"消息服務器"的通訊。 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 /** 業務處理上下文 */ export function getBusCxt () { return _busCxt }
三、組件
組件只實現了 用戶注冊、主界面容器、消息發送和消息接受等。組件只會引用store目錄中相關類,不會直接引用管道類。
- Login.vue:用戶注冊組件
- HChat.vue:主界面容器組件
- Message/MsgWriter.vue:發送消息組件
- Message/MsgList.vue:接受和顯示消息列表組件
如何運行實例
- 源碼地址[2019-09-11更新,由於原下載地址失效]
- cnpm run install 安裝所有的依賴
- npm run sokcetIo 啟動消息服務器
- npm run dev 啟動客戶端
- 示例截圖

