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:接受和显示消息列表组件
如何运行实例
- 下载源码
- cnpm run install 安装所有的依赖
- npm run sokcetIo 启动消息服务器
- npm run dev 启动客户端
- 示例截图
- Sqoop抽取Hive Parquet表数据到MySQL异常分析
- Hue中使用Oozie创建Ssh工作流时sudo命令执行失败问题分析
- [译]Safari URL重定向漏洞(CVE-2016-4585)利用分析
- Hive中的Timestamp类型日期与Impala中显示不一致分析(补充)
- 百篇(5):FeignClient 在不同场景中的应用
- 如何使用Hue上创建一个完整Oozie工作流
- MySQL远程代码执行/权限提升漏洞的分析与实践(CVE-2016-6662)
- 如何在CDH集群上部署Python3运行环境及运行Python作业
- Hacking Aria2 RPC Daemon
- 如何修改CDH集群的DataNoe节点HOSTNAME
- Sparkjava Framework 文件遍历漏洞(CVE-2016-9177)分析与探究
- 绕过混合内容警告 - 在安全的页面加载不安全的内容
- 如何在Kerberos环境使用Flume采集Kafka数据并写入HDFS
- 熊市里生成几个BTC靓号,冷存储起来装死吧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 小程序文件下载并保存文件名打开
- 分享个 CTF 小工具 bruteHASH
- centos配置mutt和msmtp实现邮件发送
- CentOS8 安装 jdk8 / java8的教程(推荐)
- Ubuntu18.04 一键升级Python所有第三方包 及安装python包的方法
- 详解centos7上elastic search安装及填坑记
- Linux利用Sysctl命令调整内核参数
- 在ubuntu16.04上创建matlab的快捷方式(实现方法)
- CentOS 7.6 Telnet服务搭建过程(Openssh升级之战 第一任务备用运输线搭建)
- Ubuntu18.04下安装MySQL(图文教程)
- 基于 ffmpeg+Webassembly 实现视频帧提取
- Ubuntu14.04 opencv2.4.8和opencv3.3.1多版本共存的实现方法
- 解决Unixbench安装报错信息的问题
- 关于安装LNMP集成包后上传图片报500错误的解决方法
- linux下SVN配置实现项目目录自动更新以及源码安装的操作方法