angular8.0聊天IM实战|高仿微信界面聊天室angular版



  • 一、项目介绍
    运用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",
      "aboutMe": "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",
      },
      "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",
      }
    }
    
    /*
     *  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 {}
    
    /*
     *  @tmpl 登录模板
     */
    
    import { Component, OnInit } from '@angular/core'
    import { Router } from '@angular/router'
    
    // 引入状态管理
    import { Store } from '@ngrx/store'
    import { Observable } from 'rxjs'
    
    import * as actions from '../../ngrx/action'
    
    declare var wcPop: any;
    
    import { getToken, checkTel } from '../../utils/common'
    
    @Component({
        selector: 'app-login',
        template: `
            <div class="wcim__lgregWrapper flexbox flex__direction-column">
                <div class="wcim__lgregHeader flex1">
                    <div class="slogan">
                        <div class="logo"><img src="../../assets/img/logo.png" /></div>
                        <h2>Angualr-chatRoom聊天室</h2>
                    </div>
                    <div class="forms">
                        <form (ngSubmit)="handleSubmit()">
                            <ul class="clearfix">
                                <li class="flexbox flex-alignc"><i class="iconfont icon-shouji"></i><input class="iptxt flex1" [(ngModel)]="formField.tel" name="tel" type="tel" placeholder="请输入手机号" autoComplete="off" maxLength="11" /><em class="borLine"></em></li>
                                <li class="flexbox flex-alignc"><i class="iconfont icon-pass"></i><input class="iptxt flex1" [(ngModel)]="formField.pwd" name="pwd" type="password" placeholder="请输入密码" autoComplete="off" /><em class="borLine"></em></li>
                            </ul>
                            
                            <div class="btns"><button class="wc__btn-primary btn__login" type="submit">登录</button></div>
                            <div class="lgregLink align-c clearfix">
                                <a routerLink="#">忘记密码</a>
                                <a routerLink="/register">注册用户</a>
                            </div>
                        </form>
                    </div>
                </div>
                <div class="wcim__lgregFooter">
                    <p class="version">Angular-chatRoom v1.0</p>
                </div>
            </div>
        `,
        styles: [``]
    })
    
    import { defaultState } from './state';
    import * as actions from './action'
    
    // 初始化数据值
    const initState: defaultState = {
        user: window.sessionStorage.getItem('user'),
        token: window.sessionStorage.getItem('token'),
        chatList: []
    }
    
    export function Auth(state = initState, action: actions.defaultAction){
        switch(action.type){
            case 'SET_TOKEN':
                return { ...state, token: action.payload }
            case 'SET_USER':
                return { ...state, user: action.payload }
            case 'SET_LOGOUT':
                return { user: null, token: null }
            default:
                return { ...state }
        }
    }
    
    /*
     *  @desc // 现在我们已经创建了reducer,但是还没有对应的action来操作它们,所以接下来就来编写action
     */
    
    import { Action } from '@ngrx/store';
    import { defaultState } from './state';
    
    // 登录验证
    export class setToken implements Action{
        readonly type = 'SET_TOKEN'
        constructor(public payload: any){
            window.sessionStorage.setItem('token', payload)
        }
    }
    
    // 设置用户名
    export class setUser implements Action {
        readonly type = 'SET_USER'
        constructor(public payload: any) {
            window.sessionStorage.setItem('user', payload)
        }
    }
    
    // 退出
    export class logout implements Action {
        readonly type = 'SET_LOGOUT'
        constructor() {
            window.sessionStorage.removeItem('user')
            window.sessionStorage.removeItem('token')
        }
    }
    
    export type defaultAction = setToken | setUser | logout