一、项目概况

基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+react-photoswipe+swiper等技术混合开发的手机端仿微信界面聊天室——reactChatRoom,实现了聊天记录下拉刷新、发送消息、表情(动图),图片、视频预览,打赏、红包等功能。

二、技术栈

  • MVVM框架:react / react-dom
  • 状态管理:redux / react-redux
  • 页面路由:react-router-dom
  • 弹窗插件:wcPop
  • 打包工具:webpack 2.0
  • 环境配置:node.js + cnpm
  • 图片预览:react-photoswipe
  • 轮播滑动:swiper

◆ package.json依赖安装:

  1. {
  2. "name": "react-chatroom",
  3. "version": "0.1.0",
  4. "private": true,
  5. "author": "andy",
  6. "dependencies": {
  7. "react": "^16.8.6",
  8. "react-dom": "^16.8.6",
  9. "react-redux": "^7.0.3",
  10. "react-router-dom": "^5.0.0",
  11. "react-scripts": "0.9.x",
  12. "redux": "^4.0.1"
  13. },
  14. "devDependencies": {
  15. "jquery": "^2.2.3",
  16. "react-loadable": "^5.5.0",
  17. "react-photoswipe": "^1.3.0",
  18. "react-pullload": "^1.2.0",
  19. "redux-thunk": "^2.3.0",
  20. "swiper": "^4.5.0",
  21. "webpack": "^1.13.1",
  22. "webpack-dev-server": "^1.12.0"
  23. },
  24. "scripts": {
  25. "start": "set HOST=localhost&&set PORT=3003 && react-scripts start",
  26. "build": "react-scripts build",
  27. "test": "react-scripts test --env=jsdom",
  28. "eject": "react-scripts eject"
  29. }
  30. }

◆ 入口页面index.js配置

  1. /*
  2. * @desc 入口页面index.js
  3. */
  4. import React from 'react';
  5. import ReactDOM from 'react-dom';
  6. // import {HashRouter as Router, Route} from 'react-router-dom'
  7. import App from './App';
  8.  
  9. // 引入状态管理
  10. import {Provider} from 'react-redux'
  11. import {store} from './store'
  12.  
  13. // 导入公共样式
  14. import './assets/fonts/iconfont.css'
  15. import './assets/css/reset.css'
  16. import './assets/css/layout.css'
  17. // 引入wcPop弹窗样式
  18. import './assets/js/wcPop/skin/wcPop.css'
  19.  
  20. // 引入js
  21. import './assets/js/fontSize'
  22.  
  23. ReactDOM.render(
  24. <Provider store={store}>
  25. <App />
  26. </Provider>,
  27. document.getElementById('app')
  28. );

◆ 页面App.js主模板

  1. import React, { Component } from 'react';
  2. import {HashRouter as Router, Route, Switch, Redirect} from 'react-router-dom'
  3. import {connect} from 'react-redux'
  4.  
  5. import $ from 'jquery'
  6. // 引入wcPop弹窗插件
  7. import { wcPop } from './assets/js/wcPop/wcPop'
  8.  
  9. // 引入地址路由
  10. import routers from './router'
  11.  
  12. // 导入顶部、底部tabbar
  13. import HeaderBar from './components/header'
  14. import TabBar from './components/tabbar'
  15.  
  16. class App extends Component {
  17. constructor(props){
  18. super(props)
  19. console.log('App主页面参数:\n' + JSON.stringify(props, null, 2))
  20. }
  21. render() {
  22. let token = this.props.token
  23. return (
  24. <Router>
  25. <div className="weChatIM__panel clearfix">
  26. <div className="we__chatIM-wrapper flexbox flex__direction-column">
  27. {/* 顶部 */}
  28. <Switch>
  29. <HeaderBar />
  30. </Switch>
  31.  
  32. {/* 主页面 */}
  33. <div className="wcim__container flex1">
  34. {/* 路由容器 */}
  35. <Switch>
  36. {
  37. routers.map((item, index) => {
  38. return <Route key={index} path={item.path} exact render={props => (
  39. !item.meta || !item.meta.requireAuth ? (<item.component {...props} />) : (
  40. token ? <item.component {...props} /> : <Redirect to={{pathname: '/login', state: {from: props.location}}} />
  41. )
  42. )} />
  43. })
  44. }
  45. {/* 初始化页面跳转 */}
  46. <Redirect push to="/index" />
  47. </Switch>
  48. </div>
  49.  
  50. {/* 底部tabbar */}
  51. <Switch>
  52. <TabBar />
  53. </Switch>
  54. </div>
  55. </div>
  56. </Router>
  57. );
  58. }
  59. }
  60.  
  61. const mapStateToProps = (state) =>{
  62. return {
  63. ...state.auth
  64. }
  65. }
  66.  
  67. export default connect(mapStateToProps)(App);

◆ react登录、注册模块 / react登录注册验证

  1. import React, { Component } from 'react';
  2. import { Link } from 'react-router-dom'
  3. import { connect } from 'react-redux';
  4.  
  5. import * as actions from '../../store/action'
  6.  
  7. // 引入wcPop弹窗插件
  8. import { wcPop } from '../../assets/js/wcPop/wcPop.js'
  9.  
  10. class Login extends Component {
  11. constructor(props) {
  12. super(props)
  13. this.state = {
  14. tel: '',
  15. pwd: '',
  16. vcode: '',
  17.  
  18. vcodeText: '获取验证码',
  19. disabled: false,
  20. time: 0
  21. }
  22. }
  23.  
  24. componentDidMount(){
  25. if(this.props.token){
  26. this.props.history.push('/')
  27. }
  28. }
  29.  
  30. render() {
  31. return (
  32. <div className="wcim__lgregWrapper flexbox flex__direction-column">
  33. ......
  34. </div>
  35. )
  36. }
  37.  
  38. // 提交表单
  39. handleSubmit = (e) => {
  40. e.preventDefault();
  41. var that = this
  42.  
  43. this.state.tel = this.refs.tel.value
  44. this.state.pwd = this.refs.pwd.value
  45. this.state.vcode = this.refs.vcode.value
  46.  
  47. if (!this.state.tel) {
  48. wcPop({ content: '手机号不能为空!', style: 'background:#ff3b30;color:#fff;', time: 2 });
  49. } else if (!checkTel(this.state.tel)) {
  50. wcPop({ content: '手机号格式不正确!', style: 'background:#ff3b30;color:#fff;', time: 2 });
  51. } else if (!this.state.pwd) {
  52. wcPop({ content: '密码不能为空!', style: 'background:#ff3b30;color:#fff;', time: 2 });
  53. } else if (!this.state.vcode) {
  54. wcPop({ content: '验证码不能为空!', style: 'background:#ff3b30;color:#fff;', time: 2 });
  55. } else {
  56. // 获取登录之前的页面地址
  57. let redirectUrl = this.props.location.state ? this.props.location.state.from.pathname : '/'
  58.  
  59. // 设置token
  60. this.props.authToken(getToken())
  61. this.props.authUser(this.state.tel)
  62.  
  63. wcPop({
  64. content: '注册成功!', style: 'background:#41b883;color:#fff;', time: 2,
  65. end: function () {
  66. that.props.history.push(redirectUrl)
  67. }
  68. });
  69. }
  70. }
  71.  
  72. // 60s倒计时
  73. handleVcode = (e) => {
  74. e.preventDefault();
  75.  
  76. this.state.tel = this.refs.tel.value
  77.  
  78. if (!this.state.tel) {
  79. wcPop({ content: '手机号不能为空!', style: 'background:#ff3b30;color:#fff;', time: 2 });
  80. } else if (!checkTel(this.state.tel)) {
  81. wcPop({ content: '手机号格式不正确!', style: 'background:#ff3b30;color:#fff;', time: 2 });
  82. } else {
  83. this.state.time = 60
  84. this.state.disabled = true
  85. this.countDown();
  86. }
  87. }
  88.  
  89. countDown = (e) => {
  90. if(this.state.time > 0){
  91. this.state.time--
  92. this.setState({
  93. vcodeText: '获取验证码(' + this.state.time + ')'
  94. })
  95. // setTimeout(this.countDown, 1000);
  96. setTimeout(() => {
  97. this.countDown()
  98. }, 1000);
  99. }else{
  100. this.setState({
  101. time: 0,
  102. vcodeText: '获取验证码',
  103. disabled: false
  104. })
  105. }
  106. }
  107. }
  108.  
  109. const mapStateToProps = (state) => {
  110. return {
  111. ...state.auth
  112. }
  113. }
  114.  
  115. export default connect(mapStateToProps, {
  116. authToken: actions.setToken,
  117. authUser: actions.setUser
  118. })(Login)

react聊天室|react+redux仿微信聊天IM实例|react仿微信界面的更多相关文章

  1. Websocket直播间聊天室教程 - GoEasy快速实现聊天室

    最近两年直播那个火啊,真的是无法形容!经常有朋友问起,我想实现一个直播间聊天或者我想开发一个聊天室, 要如何开始呢? 今天小编就手把手的教你用GoEasy做一个聊天室,当然也可以用于直播间内的互动.全 ...

  2. ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(二) 实现聊天室连接

    上一篇已经简单介绍了layim WebUI即时通讯组件和获取数据的后台方法.现在要讨论的是SingalR的内容,之前都是直接贴代码.那么在贴代码之前先分析一下业务模型,顺便简单讲一下SingalR里的 ...

  3. 基于nodejs+webSocket的聊天室(实现:加入聊天室、退出聊天室、在线人数、在线列表、发送信息、接收信息)

    1  安装 socket.io模块 npm install "socket.io": "latest" 2 app.js相关 ws = require('soc ...

  4. 真刀实战地搭建React+Webpack+Express搭建一个简易聊天室

    一.前面bb两句 因为自惭(自残)webpack配置还不够熟悉,想折腾着做一个小实例熟悉.想着七夕快到了,做一个聊天室自己和自己聊天吧哈哈.好了,可以停止bb了,说一下干货. 二. 这个项目能学到啥? ...

  5. HTML5 - websocket的应用 之 简易聊天室

    需要知识点: 前端知识 jq操作dom nodejs socket.io 关于websocket api的知识点,见上篇章<HTML5-Websocket>. 聊天室思路/原理: A和B聊 ...

  6. 利用Node.js的Net模块实现一个命令行多人聊天室

    1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...

  7. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-下载配置

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  8. python tornado websocket 多聊天室(返回消息给部分连接者)

    python tornado 构建多个聊天室, 多个聊天室之间相互独立, 实现服务器端将消息返回给相应的部分客户端! chatHome.py // 服务器端, 渲染主页 --> 聊天室建立web ...

  9. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。

    上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...

  10. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。

    前言 上一篇讲解了如何自定义右键菜单,都是前端的内容,本篇内容就一个:查询.聊天历史纪录查询,在之前介绍查找好友的那篇博客里已经提到过 Elasticsearch,今天它又要上场了.对于Elastic ...

随机推荐

  1. 10分钟彻底理解Redis的持久化机制:RDB和AOF

    作者:张君鸿 juejin.im/post/5d09a9ff51882577eb133aa9 什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL),数据都存储在内存当中,在处理客 ...

  2. Vue中调用另一个组件中自定义事件

    之前在一个场景中,遇到组件需要调用父组件中的方法tableInit(),字组件调用父组件常用的有三种方法,具体参考:https://www.cnblogs.com/jin-zhe/p/9523782. ...

  3. .netcore2.1 使用IdentityServer4 生成Token验证

    每个新技术权限验证都有一套机制,之前项目WebApi接口权限验证用的是Owin做为权限验证,而.netcore权限限制使用的是IdentityServer4,采用JWT的方法验证token. 首先使用 ...

  4. Oracle 备份数据库

    [目录] ①备份数据库(https://www.cnblogs.com/xqz0618/p/oracle_backup.html) ②定时备份数据库(https://www.cnblogs.com/x ...

  5. SSM框架中mapper和mapping.xml文件在同一个包下需要的配置

    前言 当我们在开发过程中,由于maven项目本身的限制,我们不能直接把我们的mapper.xml文件和对应mapper.java接口文件放到一起,也就是不能直接放在java包中,如图:  因为mave ...

  6. Google Chome浏览器下如何开发UHF读写器

    google Chrome浏览器不支持ocx,也就不能通过ocx来连接UHF读写器,只能使用RFID读写器云服务插件,通过javascript语言来连接和操控UHF读写器YW-602H.RFID读写器 ...

  7. 框架用多了真的会死人的,spring-cloud全家桶与mybitais 集成完整示例(附下载)

    ​ 题外话: 看到这一长串包含各种技术名词的标题,一路走来感觉研发深深的被各种框架给绑架了,从我们刚出生最简单的jsp,servlet打天下,到spring mvc的盛行,再到现在spring-boo ...

  8. LINUX中查看、添加、删除PATH以及永久添加PATH

    1.查看PATH变量 echo $PATH 会出现: 路径1:路径2:路径3 2.添加PATH变量 export PATH=$PATH:新添加的路径 用此方法添加的PATH,在关闭或者重启LINUX后 ...

  9. div里面的元素垂直均匀分布 按钮引发地址栏出现问号 判断一个数组是否为空 div底部居中 路由传参接受参数

    一个固定高度的div的子元素 在垂直 方向上平均分布 .important-dec{ height: 121px; flex-direction: column; display: flex; jus ...

  10. pytroch中cp27m和cp27mu的区别及判别方法

    python中m和mu的区别 从https://download.pytorch.org/whl中下载pytorch安装包时常会发现有相同版本的安装包有cp27m和cp27mu两种,其中cp27m是u ...