vue + socket.io實現一個簡易聊天室

     vue + vuex + elementUi + socket.io實現一個簡易的在線聊天室,提升本身在對vue系列在項目中應用的深度。由於學會一個庫或者框架容易,但要結合項目使用一個庫或框架就不是那麼容易了。功能雖然很少,但仍是有收穫。設計和實現思路較爲拙劣,懇請各位道友指正css

能夠達到的需求

  • 能查看在線用戶列表
  • 能發送和接受消息

使用到的框架和庫

  • socket.io作爲實時通信基礎
  • vuex/vue:客戶端Ui層使用
  • Element-ui:客戶端Ui組件

類文件關係圖

服務端:vue

客戶端:node

服務端實現

    實現聊天服務器的相關功能,包含通信管道的建立、用戶加入、消息的接受與轉發等。git

1、通信服務創建

    build/server-config.js:聊天服務器的入口github

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方法建立一個管道,此時的管道上是沒有用戶信息的。

2、建立上下文(服務端上下文)

實現一個聊天室上下文,包含:用戶、房間、消息、管道等數組,因此代碼都在service-server目錄中。vuex

  • 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)
}

此時會建立一個管道實例,而後初始化管道實例,並將管道添加到管道數組中。如下是初始化管道實例的代碼:express

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()
}

在初始化管道實例時作了以下事件:npm

  • 將通信socket添加一個到房間中,方便後期好廣播消息
  • 向當前鏈接上來的socket發送房間信息,設定爲第一個房間
  • 監聽三個事件:用戶註冊、新消息、關閉鏈接。此處都要邏輯處理,能夠參考源碼。

客戶端實現

    主要實現鏈接服務、註冊用戶、發送和接受消息的功能。首先以main.js爲入口,且須要先裝配好vue相關配件,如vuex、ElemUi、客戶端通信管道等,而後建立vue實例和鏈接消息服務器,代碼以下:element-ui

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)
      })
    })
  }
})

1、與服務端的通信

service-client目錄中實例的與消息服務器通信,其中包含建立用戶、接受和發送消息等。一個客戶端只能擁有一個消息管道,如下代碼是消息管理的建立:bootstrap

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實例方法,用於建立一個與消息服務器的鏈接,並接受其中房間發送回來的房間信息。而後就初始化業務層。

2、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
}

3、組件

組件只實現了 用戶註冊、主界面容器、消息發送和消息接受等。組件只會引用store目錄中相關類,不會直接引用管道類。

  • Login.vue:用戶註冊組件
  • HChat.vue:主界面容器組件
  • Message/MsgWriter.vue:發送消息組件
  • Message/MsgList.vue:接受和顯示消息列表組件

如何運行實例

  • 源碼地址[2019-09-11更新,因爲原下載地址失效]
  • cnpm run install 安裝全部的依賴
  • npm run sokcetIo 啓動消息服務器
  • npm run dev 啓動客戶端
  • 示例截圖

相關文章
相關標籤/搜索