使用nodejs和react怎么實(shí)現(xiàn)一個(gè)即時(shí)通訊聊天室功能?相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
創(chuàng)新互聯(lián)建站基于成都重慶香港及美國等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)西部信息服務(wù)器托管,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。npx create-react-app socketio-demo
進(jìn)入socketio-demo
目錄 運(yùn)行eject進(jìn)行拆包,本項(xiàng)目也可以不拆,這是個(gè)人習(xí)慣。 注意如果運(yùn)行eject命令最好在項(xiàng)目初始階段執(zhí)行,已經(jīng)開始編寫后不要再使用容易出現(xiàn)bug,新人謹(jǐn)慎使用eject命令
yarn eject
項(xiàng)目拆包后創(chuàng)建服務(wù)器文件夾和文件
mkdir server type null>index.js
創(chuàng)建完成后目錄如下
編寫即時(shí)通訊(聊天室)后臺(tái)
安裝nodejs插件
npm i express http socket.io nodemon
進(jìn)入server文件夾下的index.js頁面開始編寫后臺(tái)程序
const app = require('express')(); const server = require('http').Server(app); const io = require('socket.io')(server); //設(shè)置端口9093 server.listen(9093); //創(chuàng)建socket.io連接 io.on('connection', function (socket) { //獲取messages事件 socket.on('messages', function (data) { //向所有連接進(jìn)行廣播 socket.broadcast.emit('messages', data) //對(duì)發(fā)出者進(jìn)行廣播,用戶名加上我 data.user=data.user+'[我]' socket.emit('messages', data) }); });
編寫即時(shí)通訊(聊天室)前臺(tái)
后臺(tái)編寫完畢,可以在src目錄中編寫前臺(tái)內(nèi)容 安裝需要用到的react-router
和redux依賴
npm i redux react-redux react-router react-router-dom
在src中創(chuàng)建io文件夾 在io文件夾中創(chuàng)建所需要的文件
cd src mkdir io cd io type null>login.js type null>socket-demo.js type null>socket-demo.css mkdir auth cd auth type null>auth.js
創(chuàng)建完成后目錄如下
這里auth.js文件是用來判斷用戶是否輸入昵稱,如已輸入昵稱可以進(jìn)入聊天室,如沒有輸入昵稱則跳回登錄界面要求輸入昵稱
本項(xiàng)目當(dāng)中我們把昵稱存在redux里實(shí)現(xiàn)登錄界面和聊天室界面的共用,當(dāng)然現(xiàn)這個(gè)項(xiàng)目比較小,如果想用localStorage存在本地也可以,不過考慮到后期的擴(kuò)展性以及加深對(duì)redux的理解我還是選擇存在redux當(dāng)中
src文件夾下創(chuàng)建redux.js文件
src文件夾下創(chuàng)建redux文件夾,在redux文件夾下創(chuàng)建user.redux.js文件
cd src type null>redux.js mkdir redux cd redux type null>user.redux.js
新建目錄如下
在redux文件夾下的user.redux.js中創(chuàng)建存儲(chǔ)用戶昵稱的reducer
const SET_USERNAME='SET_USERNAME' //初始化倉庫 const initState={user:''} //根據(jù)動(dòng)作改變倉庫 export function User(state = initState, action) { switch (action.type) { case SET_USERNAME: return {...state,user:action.payload} default: return state } } //寫入昵稱動(dòng)作 export function setUserName(user) { return { type:SET_USERNAME, payload:user } }
在src/redux.js文件中創(chuàng)建倉庫 combineReducers用于多個(gè)reducer的合并,這個(gè)項(xiàng)目中也可以不加,單為了后期擴(kuò)展加入使用
import { combineReducers, createStore } from 'redux' import {User} from './redux/user.redux' //window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 用于chrome redux的擴(kuò)展項(xiàng) let reducer = combineReducers({ User }) let store = createStore( reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) export default store
這樣就可以在頁面當(dāng)中使用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 時(shí)安裝 @babel/plugin-proposal-decorators
npm i @babel/plugin-proposal-decorators
在package.json中babel項(xiàng)中配置,注意plugins放在presets前否則容易報(bào)錯(cuò)
"babel": { "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }] ], "presets": [ "react-app" ] }
好了這樣就可以使用裝飾付了
下面我們來編寫判斷是否設(shè)置用戶名的程序 打開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
編寫輸入昵稱并跳轉(zhuǎn)步驟 打開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) } //鍵盤點(diǎn)擊跳轉(zhuǎn) 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 }) } //賦值并跳轉(zhuǎn)到聊天室頁面 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連接后臺(tái) 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) } //鼠標(biāo)回車事件 onKeyDown(e){ switch (e.keyCode) { case 13: this.send(); return; default: return; } } //向后臺(tái)發(fā)送信息 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 (); } } export default SocketDemo;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}) }) }
最后加上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" },
運(yùn)行后臺(tái) yarn server
運(yùn)行前臺(tái) yarn start
啟動(dòng)程序
看完上述內(nèi)容,你們掌握使用nodejs和react怎么實(shí)現(xiàn)一個(gè)即時(shí)通訊聊天室功能的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝各位的閱讀!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。