• vue + socket.io实现一个简易聊天室


         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 启动客户端
    • 示例截图

  • 相关阅读:
    基于文件数据库的规则引擎处理海量高复杂度数据(二,解决方案)
    内存数据库内核开发 工作日志(innodb的原理,算法详细剖析)(九)
    swift检测字符串是否在数组字符串中
    swift cell自定义左滑手势处理
    rxswift cell按钮绑定的重用问题
    swift代码统一编码规范
    TZImagePickerController获取原图
    swift 地区选择器选中数据操作
    iOS是否审核需要关闭一些操作
    项目概要评审
  • 原文地址:https://www.cnblogs.com/cqhaibin/p/6506182.html
Copyright © 2020-2023  润新知