angular版聊天室|仿微信界面IM聊天|NG2+Node聊天实例
程序员文章站
2022-05-26 15:45:31
一、项目介绍 运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技术实现开发的仿微信angular版聊天室angular-chatroom实例项目,实现了下拉刷新、聊天消息右键菜单、发送消息、表情(动图), ......
一、项目介绍
运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcpop等技术实现开发的仿微信angular版聊天室angular-chatroom实例项目,实现了下拉刷新、聊天消息右键菜单、发送消息、表情(动图),图片、视频预览,红包打赏等功能。
二、技术实现
- mvvm框架:angular8.0 / @angular/cli
- 状态管理:@ngrx/store / rxjs
- 地址路由:@angular/router
- 弹窗组件:wcpop
- 打包工具:webpack 2.0
- 环境配置:node.js + cnpm
- 图片预览:previewimage
- 轮播滑动:swiper
{ "name": "angular-chatroom", "contact": "qq:282310962 、 wx:xy190310", "dependencies": { "@angular/animations": "~8.0.1", "@angular/common": "~8.0.1", "@angular/compiler": "~8.0.1", "@angular/core": "~8.0.1", "@angular/forms": "~8.0.1", "@angular/platform-browser": "~8.0.1", "@angular/platform-browser-dynamic": "~8.0.1", "@angular/router": "~8.0.1", "rxjs": "~6.4.0", "tslib": "^1.9.0", "zone.js": "~0.9.1" }, "devdependencies": { "@angular-devkit/build-angular": "~0.800.0", "@angular/cli": "~8.0.3", "@angular/compiler-cli": "~8.0.1", "@angular/language-service": "~8.0.1", "@ngrx/store": "^8.0.1", "@types/jasmine": "~3.3.8", "@types/jasminewd2": "~2.0.3", "@types/node": "~8.9.4", "@types/swiper": "^4.4.3", "codelyzer": "^5.0.0", "jasmine-core": "~3.4.0", "jasmine-spec-reporter": "~4.2.1", "jquery": "^2.2.3", "karma": "~4.1.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "~2.0.1", "karma-jasmine": "~2.0.1", "karma-jasmine-html-reporter": "^1.4.0", "swiper": "^4.5.0", "typescript": "~3.4.3" } }
◆ app主页面模板、app-routing路由地址配置
<div class="wechatim__panel clearfix"> <div class="we__chatim-wrapper flexbox flex__direction-column"> <!-- 顶部 --> <header-bar></header-bar> <!-- 主页面 --> <div class="wcim__container flex1"> <router-outlet></router-outlet> </div> <!-- 底部 --> <tab-bar></tab-bar> </div> </div>
/* * angular/router路由配置 */ import { ngmodule } from '@angular/core' import { routes, routermodule } from '@angular/router' // 引入路由验证 import { auth } from '../views/auth/auth' // 引入页面组件 import { notfoundcomponent } from '../components/404' import { logincomponent } from '../views/auth/login' import { registercomponent } from '../views/auth/register' import { indexcomponent } from '../views/index' import { contactcomponent } from '../views/contact' import { uinfocomponent } from '../views/contact/uinfo' import { ucentercomponent } from '../views/ucenter' import { groupchatcomponent } from '../views/chat/group-chat' import { groupinfocomponent } from '../views/chat/group-info' import { singlechatcomponent } from '../views/chat/single-chat' export const routes: routes = [ { path: '', redirectto: 'index', pathmatch: 'full', data: { showheader: true, showtabbar: true }, }, // 登录、注册 { path: 'login', component: logincomponent, }, { path: 'register', component: registercomponent, }, // 首页、联系人、我 { path: 'index', component: indexcomponent, canactivate: [auth], data: { showheader: true, showtabbar: true }, }, { path: 'contact', component: contactcomponent, canactivate: [auth], data: { showheader: true, showtabbar: true }, }, { path: 'contact/uinfo', component: uinfocomponent }, { path: 'ucenter', component: ucentercomponent, canactivate: [auth], data: { showheader: false, showtabbar: true }, }, // 聊天页面 { path: 'chat/group-chat', component: groupchatcomponent, canactivate: [auth] }, { path: 'chat/single-chat', component: singlechatcomponent, canactivate: [auth] }, { path: 'chat/group-info', component: groupinfocomponent, canactivate: [auth] }, // 404 { path: '**', component: notfoundcomponent, }, // ... ]; @ngmodule({ // imports: [routermodule.forroot(routes)], imports: [routermodule.forroot(routes, { usehash: true })], //开启hash模式 exports: [routermodule], providers: [auth] }) export class approutingmodule {}
◆ angular + ngrx/store页面状态管理
◆ angular登录、注册验证
export class logincomponent implements oninit { private formfield = { tel: '', pwd: '' } private auth: any constructor( private router: router, private store: store<{}> ) { let that = this this.store.select('auth').subscribe(v => { console.log(v) that.auth = v; }) } ngoninit(): void { if(this.auth.token){ this.router.navigate(['/index']) } } handlesubmit(){ let that = this if(!this.formfield.tel){ wcpop({ content: '手机号不能为空!', style: 'background:#eb5a5c;color:#fff;', time: 2 }); }else if(!checktel(this.formfield.tel)){ wcpop({ content: '手机号格式不正确!', style: 'background:#eb5a5c;color:#fff;', time: 2 }); }else if(!this.formfield.pwd){ wcpop({ content: '密码不能为空!', style: 'background:#eb5a5c;color:#fff;', time: 2 }); }else{ this.store.dispatch(new actions.settoken(gettoken(64))) this.store.dispatch(new actions.setuser(this.formfield.tel)) wcpop({ content: '登录成功,跳转中...', style: 'background:#378fe7;color:#fff;', time: 2, shadeclose: false, end: function () { that.router.navigate(['/index']) } }); } } }
◆ 编辑器核心消息处理
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); } } } // 消息处理 function isempty() { // var html = $editor.html(); var html = $(".j__wceditor").html(); html = html.replace(/<br[\s\/]{0,2}>/ig, "\r\n"); html = html.replace(/<[^img].*?>/ig, ""); html = html.replace(/ /ig, ""); return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == ""; }