Socket.io +react + egg聊天室
程序员文章站
2022-07-10 21:22:01
...
技术栈:
前端:react
后端:egg
通信手段:socket.io
官方API: https://socket.io/get-started/chat/
socket.io的工作流程:
客户端 =》服务端 =》客户端
socket.io: 通俗易懂的来讲,比如说你喜欢隔壁班的李小花,你想一下让全学校的人都知道,怎么办?
当让是去广播站,然后让他帮你广播一下,然后全学校的人收到消息,哦,张全蛋喜欢李小花;
下面简单的实现一个在线果聊。。。
效果图如下:
首先进入登录页,输入用户名进入聊天室,如果用户不存在,那么添加到数据库,然后进入聊天室,如果用户存在,那么提示用户已存在,然后重新输入用户名。
react: src/view/ChatRoom/index.js
import React, { Component , Fragment} from 'react';
import io from 'socket.io-client';
import './style.css';
import Axios from 'aaa@qq.com@axios';
class ChatRoom extends Component {
constructor(props) {
super(props);
this.state = {
userNameIpt:'',//login 的用户名
userSay:'',//聊天室里的input
hide:true,//隐藏聊天室
socket:io('http://192.168.31.3:3333'),//配置socket
userName:'',//进入聊天室之后保存的用户名
wordList:[]//聊天记录
}
}
render() {
let {userNameIpt,userSay,hide,wordList,userName} = this.state;
return (
<div className="chatRoom">
<input type='text'
value={userNameIpt}
onChange={this.changeIpt.bind(this)}
name="userNameIpt"
onKeyDown={this.setUser.bind(this)}
placeholder="输入用户名,按下回车"
/>
<div className={hide?'chatMask hide':'chatMask'}>
<header>聊天室</header>
<ul>
{
wordList && wordList.map((item,index)=>{
return (
<li key={index}>
<b>{item.userName}</b>
<span>{item.userSay}</span>
</li>
)
})
}
</ul>
<footer>
<input type="text" value={userSay} onChange={this.changeIpt.bind(this)} name="userSay"/>
<button onClick={this.sendUserSay.bind(this)}>发送</button>
</footer>
</div>
</div>
);
}
changeIpt(e){
this.setState({ [e.target.name]:e.target.value });
}
setUser(e){
let {userNameIpt,userName} = this.state;
if(e.keyCode===13){
//发送注册请求
Axios
.post('/login',{
userNameIpt
})
.then(res=>{
if(res.data.code===0){
//用户存在
}else{
//用户不存在,成功注册
console.log(res.data)
this.setState({ userName:res.data.flag.userName , hide:false });
//注册成功保存用户名 然后 做显示聊天室
}
alert(res.data.msg)
})
// this.setState({ hide:false });
}
}
sendUserSay(){
let {socket,userSay,userName} = this.state;
socket.emit('message',{
userSay,
userName
})
this.setState({ userSay:'' });
}
componentDidMount(){
let {socket,wordList} = this.state;
socket.on('showMsg',(data)=>{
console.log(data)
wordList.push(data)
this.setState({ wordList });
})
}
}
export default ChatRoom;
socket: socket/app.js
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
console.log('一个用户连接了');
socket.on('message',function (data) {
let {userSay,userName} = data;
socket.emit('showMsg',{userSay,userName})//对用户自己的
socket.broadcast.emit('showMsg',{userSay,userName})//广播的
})
});
http.listen(3333, function(){
console.log('listening on *:3333');
});
egg: egg/app/router.js
'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const { router, controller } = app;
router.post('/login', controller.login.index)
};
egg:egg/app/controller/login.js
'use strict';
const Controller = require('egg').Controller;
class LoginController extends Controller {
async index() {
const { ctx } = this;
let userNameIpt = ctx.request.body.userNameIpt;
let result = await ctx.service.login.set(userNameIpt);
ctx.body = result;
}
}
module.exports = LoginController;
egg: egg/app/service/login.js
module.exports = app => {
const uid = require('uid')
class LoginService extends app.Service {
async set(userNameIpt) {
let flag = await this.app.mysql.get('userList',{
userName:userNameIpt
})
if(flag){
return {
code:0,
msg:'用户存在'
}
}else{
let result = await this.app.mysql.insert('userList',{
userName:userNameIpt,
id:uid(10)
})
let flag = await this.app.mysql.get('userList',{
userName:userNameIpt
})
return {
code:1,
msg:'注册成功',
flag
}
}
}
}
return LoginService
}
中途遇到的几个坑:
- 服务端渲染 需要在index.html里引入 script 标签 socket.io.js
- 在Vue or React 里,客户端需要执行 cnpm install socket.io --save
- 引入后,配置时候需要注意 io(’‘http://localhost:3333") 需要别人访问的时候改成具体的 io(’'http://192.168.2.11:3333") ;
上一篇: Socket.io在线聊天室