react网页版聊天|仿微信、微博web版|react+pc端仿微信实例
程序员文章站
2022-04-11 07:49:53
一、项目介绍 基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+nodejs等技术混合开发的仿微信web端聊天室reactWebChat项目,实现了聊天记录右键菜单、发送消息、表情(动图),图片、视频预览,浏览器截图粘贴发 ......
一、项目介绍
基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+nodejs等技术混合开发的仿微信web端聊天室reactwebchat项目,实现了聊天记录右键菜单、发送消息、表情(动图),图片、视频预览,浏览器截图粘贴发送等功能。
二、技术选型
- mvvm框架:react / react-dom
- 状态管理:redux / react-redux
- 页面路由:react-router-dom
- 弹窗插件:wcpop
- 打包工具:webpack 2.0
- 环境配置:node.js + cnpm
- 图片预览:react-photoswipe
- 轮播滑动:swiper
{ "name": "react-webchat", "version": "0.1.0", "private": true, "dependencies": { "react": "^16.8.6", "react-dom": "^16.8.6", "react-redux": "^7.1.0", "react-router-dom": "^5.0.1", "react-scripts": "0.9.x", "redux": "^4.0.1", "redux-thunk": "^2.3.0" }, "devdependencies": { "jquery": "^2.2.3", "react-custom-scrollbars": "^4.2.1", "react-photoswipe": "^1.3.0", "swiper": "^4.5.0" }, "scripts": { "start": "set host=localhost&& set port=3003 && react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } }
◆ app主页面布局及路由配置:
render() { let token = this.props.token return ( <router> <div classname="vchat-wrapper flexbox flex-alignc"> <div classname="vchat-panel" /*style={{ backgroundimage: `url(${require("./assets/img/placeholder/vchat__panel-bg02.jpg")})` }}*/ > <div classname="vchat-inner flexbox"> {/* //顶部(最大、最小、关闭) */} <switch> <winbar /> </switch> {/* //侧边栏 */} <switch> <sidebar /> </switch> {/* //主页面 */} <div classname="flex1 flexbox"> {/* 路由容器 */} <switch> { routers.map((item, index) => { return <route key={index} path={item.path} exact render={props => ( !item.meta || !item.meta.requireauth ? (<item.component {...props} />) : ( token ? <item.component {...props} /> : <redirect to={{pathname: '/login', state: {from: props.location}}} /> ) )} /> }) } {/* 初始化页面跳转 */} <redirect push to="/index" /> </switch> </div> </div> </div> </div> </router> ); }
◆ react+react-redux配合状态管理:
import {combinereducers} from 'redux' import defaultstate from './state.js' function auth(state = defaultstate, action) { // 不同的action处理不同的逻辑 switch (action.type) { case 'set_token': return { ...state, token: action.data } case 'set_user': return { ...state, user: action.data } case 'set_logout': return { user: null, token: null } default: return { ...state } } }
◆ react页面路由配置:
/* * @desc 页面地址路由js */ // 引入页面组件 import login from '../views/auth/login' import register from '../views/auth/register' import index from '../views/index' import contact from '../views/contact' import uinfo from '../views/contact/uinfo' import newfriend from '../views/contact/new-friends' import ucenter from '../views/ucenter' import news from '../views/news' import newsdetail from '../views/news/detail'; export default [ { path: '/login', name: 'login', component: login, meta: { hidesidebar: true }, }, { path: '/register', name: 'register', component: register, meta: { hidesidebar: true }, }, { path: '/index', name: 'app', component: index, meta: { requireauth: true }, }, { path: '/contact', name: 'contact', component: contact, meta: { requireauth: true }, }, { path: '/contact/uinfo', name: 'uinfo', component: uinfo, }, { path: '/contact/new-friends', name: 'newfriend', component: newfriend, meta: { requireauth: true }, }, { path: '/news', name: 'news', component: news, }, { path: '/news/detail', name: 'newsdetail', component: newsdetail, }, { path: '/ucenter', name: 'ucenter', component: ucenter, meta: { requireauth: true }, }, // ... ]
import react, { component } from 'react'; import { link } from 'react-router-dom'; import {connect} from 'react-redux' import $ from 'jquery' // 引入wcpop弹窗插件 import { wcpop } from '../../assets/js/wcpop/wcpop' // 引入自定义滚动条 import { scrollbars } from 'react-custom-scrollbars' // 引入swiper import swiper from 'swiper' import 'swiper/dist/css/swiper.css' // 引入图片预览组件react-photoswipe import {photoswipe} from 'react-photoswipe' import 'react-photoswipe/lib/photoswipe.css' // 导入消息记录列表 import recordlist from '../../components/recordlist'
// >>> 【编辑器+表情处理模块】------------------------------------------ // ...处理编辑器信息 function surrounds() { settimeout(function () { //chrome var sel = window.getselection(); var anchornode = sel.anchornode; if (!anchornode) return; if (sel.anchornode === $(".j__wceditor")[0] || (sel.anchornode.nodetype === 3 && sel.anchornode.parentnode === $(".j__wceditor")[0])) { var range = sel.getrangeat(0); var p = document.createelement("p"); range.surroundcontents(p); range.selectnodecontents(p); range.insertnode(document.createelement("br")); //chrome sel.collapse(p, 0); (function clearbr() { var elems = [].slice.call($(".j__wceditor")[0].children); for (var i = 0, len = elems.length; i < len; i++) { var el = elems[i]; if (el.tagname.tolowercase() == "br") { $(".j__wceditor")[0].removechild(el); } } elems.length = 0; })(); } }, 10); } // 定义最后光标位置 var _lastrange = null, _sel = window.getselection && window.getselection(); var _rng = { getrange: function () { if (_sel && _sel.rangecount > 0) { return _sel.getrangeat(0); } }, addrange: function () { if (_lastrange) { _sel.removeallranges(); _sel.addrange(_lastrange); } } } // 格式化编辑器包含标签 $("body").on("click", ".j__wceditor", function(){ $(".wc__choose-panel").hide(); _lastrange = _rng.getrange(); }); $("body").on("focus", ".j__wceditor", function(){ surrounds(); _lastrange = _rng.getrange(); }); $("body").on("input", ".j__wceditor", function(){ surrounds(); _lastrange = _rng.getrange(); });
上一篇: WebGL场景的两种地面构造方法
下一篇: C#实现Dev Grid拖拽移动行的方法