最近一直在學習angular技術,一頓研究下來發現並沒想象的困難,不過倒是採坑了不少,後面通過網絡及社區都解決了。之前就有使用vue.js react做過一些項目實戰。今天要給大家分享的是angular聊天室案例。
項目簡述:
使用angular8+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技術開發的高仿微信界面angular版聊天室實例項目,實現了下拉刷新、聊天消息右鍵菜單、發送消息、表情(動圖),圖片、視頻預覽,紅包打賞等功能。
技術實現:
- MVVM框架:angular8.0 / @angular/cli
- 狀態管理:@ngrx/store / rxjs
- 地址路由:@angular/router
- 彈窗組件:wcPop
- 打包工具:webpack 2.0
- 圖片預覽:previewImage
- 輪播滑動:swiper
app主頁面模板
整體採用flex佈局,頂部/底部導航條是自定義組件,作爲公共部分引入即可。
<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頁面路由地址配置:
Auth爲判斷是否登錄攔截,通過NG提供的canActivate方法進行頁面驗證
/*
* 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 {}
export class Auth implements CanActivate{
constructor(private router: Router){}
canActivate(){
let that = this
// 驗證token
const token: boolean = window.sessionStorage.getItem('token') ? true : false
if(!token){
// 未登錄授權
/*
wcPop({
content: '還未登錄授權!', anim: 'shake', style: 'background:#e03b30;color:#fff;', time: 2,
end: function () {
that.router.navigate(['/login']);
}
});
*/
that.router.navigate(['/login']);
}
return token
}
}
angular頁面狀態管理:
不同於vue通過vuex進行狀態管理,react通過react-redux/redux進行狀態管理,而angular則通過@ngrx/store進行狀態管理
登錄、註冊模塊:
項目中使用的彈窗則是自己開發的 wcPop 彈出框插件, 功能效果還ok~~, 支持多種參數配置,內置多種效果,具體的可以去看看這篇文章介紹😝 https://www.cnblogs.com/xiaoyan2017/p/8695783.html
export class LoginComponent implements OnInit {
private formField = {
tel: '',
pwd: ''
}
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, "") == "";
}
好了,以上就是今天的分享,希望以後能給大家分享更多知識。希望能喜歡😍😍
附上最近開發的項目實例 ~~~
vue聊天web端:https://blog.csdn.net/yanxinyun1990/article/details/89735778
react聊天室:https://blog.csdn.net/yanxinyun1990/article/details/93230368