侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

nodejs和react实现即时通讯简易聊天室功能

前端  /  管理员 发布于 4年前   218

npx create-react-app socketio-demo

进入socketio-demo目录 运行eject进行拆包,本项目也可以不拆,这是个人习惯。 注意如果运行eject命令最好在项目初始阶段执行,已经开始编写后不要再使用容易出现bug,新人谨慎使用eject命令

yarn eject

项目拆包后创建服务器文件夹和文件

mkdir servertype null>index.js

创建完成后目录如下

 

编写即时通讯(聊天室)后台

安装nodejs插件

npm i express http socket.io nodemon

进入server文件夹下的index.js页面开始编写后台程序

const app = require('express')(); const server = require('http').Server(app); const io = require('socket.io')(server); //设置端口9093 server.listen(9093); //创建socket.io连接 io.on('connection', function (socket) {  //获取messages事件  socket.on('messages', function (data) {   //向所有连接进行广播  socket.broadcast.emit('messages', data)   //对发出者进行广播,用户名加上我  data.user=data.user+'[我]'  socket.emit('messages', data)  }); });

编写即时通讯(聊天室)前台

后台编写完毕,可以在src目录中编写前台内容 安装需要用到的react-router和redux依赖

npm i redux react-redux react-router react-router-dom

在src中创建io文件夹 在io文件夹中创建所需要的文件

cd srcmkdir iocd iotype null>login.jstype null>socket-demo.jstype null>socket-demo.cssmkdir authcd authtype null>auth.js

创建完成后目录如下

 

这里auth.js文件是用来判断用户是否输入昵称,如已输入昵称可以进入聊天室,如没有输入昵称则跳回登录界面要求输入昵称

本项目当中我们把昵称存在redux里实现登录界面和聊天室界面的共用,当然现这个项目比较小,如果想用localStorage存在本地也可以,不过考虑到后期的扩展性以及加深对redux的理解我还是选择存在redux当中

src文件夹下创建redux.js文件

src文件夹下创建redux文件夹,在redux文件夹下创建user.redux.js文件

cd srctype null>redux.jsmkdir reduxcd reduxtype null>user.redux.js

新建目录如下

 

在redux文件夹下的user.redux.js中创建存储用户昵称的reducer

const SET_USERNAME='SET_USERNAME' //初始化仓库 const initState={user:''} //根据动作改变仓库  export function User(state = initState, action) {  switch (action.type) {   case SET_USERNAME:    return {...state,user:action.payload}   default:    return state  } } //写入昵称动作 export function setUserName(user) {  return {   type:SET_USERNAME,  payload:user  } }

在src/redux.js文件中创建仓库 combineReducers用于多个reducer的合并,这个项目中也可以不加,单为了后期扩展加入使用

import { combineReducers, createStore } from 'redux' import {User} from './redux/user.redux' //window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 用于chrome redux的扩展项let reducer = combineReducers({ User }) let store = createStore(  reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())  export default store

这样就可以在页面当中使用redux了

下一步在app.js中引入redux,并把路由搭建起来 在src/app.js中写入

import React from 'react';import {HashRouter as Router,Route,Switch} from 'react-router-dom'import Login from "./io/login";import SocketDemo from "./io/socket-demo";import {Provider} from 'react-redux'import store from './redux'import Auth from "./io/auth/auth";function App() { return (                                 );}export default App;

在写页面之前我们先安装修饰符插件

npm i babel-plugin-transform-decorators-legacy

Babel >= 7.x 时安装 @babel/plugin-proposal-decorators

npm i @babel/plugin-proposal-decorators

在package.json中babel项中配置,注意plugins放在presets前否则容易报错

"babel": {  "plugins": [   ["@babel/plugin-proposal-decorators", { "legacy": true }]  ],  "presets": [   "react-app"  ] }

好了这样就可以使用装饰付了

下面我们来编写判断是否设置用户名的程序 打开src/io/auth下的auth.js文件

import React from 'react'; import {connect} from 'react-redux' import {withRouter} from 'react-router-dom' //获取reducer @connect(  state=>state,  {} ) //获取router @withRouter class Auth extends React.Component{  componentDidMount() {   //如果有用户名就跳到聊天页,如没有则跳到登陆页。  if(this.props.User.user){    this.props.history.push('/talk')   }else {    this.props.history.push('/')   }  }  render() {   return null  } }  export default Auth

编写输入昵称并跳转步骤 打开src/io/login.js文件

import React from 'react';import './socket-demo.css';import {connect} from 'react-redux'import {setUserName} from '../redux/user.redux'@connect( null, {setUserName})class Login extends React.Component{ constructor(props) {  super(props);  this.state={   user:''  }  this.login=this.login.bind(this)  this.onKeyDown=this.onKeyDown.bind(this) } //键盘点击跳转  onKeyDown(e){  switch (e.keyCode) {   case 13:    this.login();    return;   default:    return;  } } //添加键盘事件  componentDidMount() {  document.addEventListener("keydown", this.onKeyDown) } //赋值state  handleChange(title,target){  this.setState({   [title]:target.target.value  }) } //赋值并跳转到聊天室页面  login(){  let {user}=this.state;  if(user!==null && user.trim()!==''){   this.props.setUserName(user);   this.props.history.push('/talk')  } } render() {  return (   
this.handleChange('user',v)} /> ); }}export default Login

下面是重头戏,聊天室的前端展示的核心代码 打开src/iosocket-demo.js文件

import React from 'react'import io from 'socket.io-client'import {connect} from 'react-redux'import './socket-demo.css'const url='ws://localhost:9093'const socket = io(url);@connect( state=>state, {})class SocketDemo extends React.Component{ constructor(props) {  super(props);  this.state={   message:'',   user:this.props.User.user,   messages:[]  }  this.send=this.send.bind(this)  this.login=this.login.bind(this)  this.onKeyDown=this.onKeyDown.bind(this) } componentDidMount() {  //输入欢迎信息   this.login()  //增加回车事件   document.addEventListener("keydown", this.onKeyDown)  //socket.io连接后台   io(url).on('connect', ()=>{   console.log('connect');   socket.on('messages', data => {    //返回用户列表     this.setState({     messages:[...this.state.messages,data]    })    if(this.refs.showDiv){     this.refs.showDiv.scrollTop=2000    }   });  }); } componentWillUnmount() {  //断开socket io连接   io('ws://localhost:9093').on('disconnect', function(){   console.log('disconntect');  });  document.removeEventListener("keydown", this.onKeyDown) } //鼠标回车事件  onKeyDown(e){  switch (e.keyCode) {   case 13:    this.send();    return; default:    return;  } } //向后台发送信息  send(){  let {user,message}=this.state;  console.log(this.refs.showDiv);  socket.emit('messages', {user,message});  this.setState({   message:''  }) } login(){  let user=this.props.User.user;  const obj={user:'作者',message:`欢迎${user}来到聊天室`}  if(user.trim()!==''){   this.setState({    user:user,    messages:[obj]   })  } } //赋值state  handleChange(title,target){  this.setState({   [title]:target.target.value  }) } render() {  let cn='showInfo'  return (       
this.handleChange('message',v)} value={this.state.message} />
{ this.state.messages.map((v,index)=>{ if(index===0){ cn='titleInfo' }else{ cn='showInfo' } return (
{v.user}: {v.message} ) }) } ); }}export default SocketDemo;

最后加上src/iosocket-demo.css

body{   background: #008DB7;  font-family: 'Microsoft YaHei UI';  } .loginDiv{   text-align: center;  margin: 150px auto 0;  width: 250px; } .loginDiv input[type='text']{   display: inline-block;  box-sizing: border-box;  border-radius: 5px;  padding-left: 5px;  border: none;  width: 250px;  height: 35px;  line-height: 35px; } .loginDiv button{   display: inline-block;  box-sizing: border-box;  border-radius: 5px;  padding-left: 5px;  border: none;  width: 250px;  height: 35px;  line-height: 35px;  margin-top: 10px;  background: #0067A2;  color: #ffffff; }  .talkDiv{   position: fixed;  top: 0;  left: 0;  right: 0;  bottom: 0; }  .talkDiv .operatingDiv{   position: fixed;  bottom: 0;  left: 0;  right: 0;  height: 40px;  display: flex; }  .talkDiv .operatingDiv input[type='text']{   flex: 1;  height: 40px;  line-height: 40px;  box-sizing: border-box;  padding-left: 10px; } .talkDiv .operatingDiv button{   display: inline-block;  box-sizing: border-box;  border-radius: 5px;  border: none;  width: 250px;  height: 40px;  line-height: 40px;  background: #0067A2;  color: #ffffff; }  .talkDiv .showDiv{   position: fixed;  bottom: 40px;  left: 0;  right: 0;  top: 0;  font-size: 16px;  color: #ffffff;  overflow: auto; } .talkDiv .showDiv .titleInfo{   padding: 10px;  color: yellow;  font-size: 20px; } .talkDiv .showDiv .showInfo{   padding: 10px; }

在package.json中加入命令行

"scripts": {  "start": "node scripts/start.js",  "build": "node scripts/build.js",  "server": "nodemon server/index.js"},
  • 运行后台 yarn server
  • 运行前台 yarn start

启动程序

总结

以上所述是小编给大家介绍的nodejs和react实现即时通讯简易聊天室功能,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

您可能感兴趣的文章:

  • NodeJs 实现简单WebSocket即时通讯的示例代码
  • nodejs结合Socket.IO实现的即时通讯功能详解
  • nodejs和react实现即时通讯简易聊天室功能
  • nodejs+express搭建多人聊天室步骤
  • Nodejs实现多房间简易聊天室功能
  • 基于Nodejs利用socket.io实现多人聊天室
  • 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
  • nodejs实现的一个简单聊天室功能分享


  • 上一条:
    vue element 生成无线级左侧菜单的实现代码
    下一条:
    深入理解Vue keep-alive及实践总结
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客