react+web版聊天|仿微信网页聊天实战

4,149 阅读2分钟

一、介绍

采用react全家桶技术 react+react-dom+react-router-dom+redux+react-redux+nodejs等技术混合开发的仿微信web端聊天室reactWebChat项目,实现了聊天记录右键菜单、发送消息、表情(动图),图片、视频预览,浏览器截图粘贴发送等功能。

二、技术

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






/*
    引入公共及全局组件配置
    Q:282310962
    https://www.cnblogs.com/xiaoyan2017
*/
import React from 'react';import ReactDOM from 'react-dom';import App from './App';
// 引入状态管理import { Provider } from 'react-redux'import { store } from './store'
// 导入公共样式import './assets/fonts/iconfont.css'import './assets/css/reset.css'import './assets/css/layout.css'// 引入wcPop弹窗样式import './assets/js/wcPop/skin/wcPop.css'
ReactDOM.render(  <Provider store={store}>    <App />  </Provider>,  document.getElementById('root'));

{  "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"  }}

/*
 *  @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 },
    },

    // ...
]

// >>> 【编辑器+表情处理模块】------------------------------------------
// ...处理编辑器信息
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();
});

欢迎关注我的技术博客:blog.csdn.net/yanxinyun19…

一起学习,一起进步,有问题随时联系,一起解决!!!