angular高仿微信聊天界面|NG2聊天IM社交|angular仿微信表情輸入框

最近一直在學習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(/&nbsp;/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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章