Angular + NG-ZORRO快速開發一個後臺系統

2022-04-21 13:00:31
本篇文章給大家分享一個實戰,瞭解一下angualr 結合 ng-zorro 如何快速開發一個後臺系統,希望對大家有所幫助!

連更的這幾天的文章,我們已經瞭解了不少 angular 的知識點了,這次我們來個小成品。

angualr 結合 ng-zorro 快速且規範的開發一個後臺系統。【相關教學推薦:《》】

系統功能包括下面的內容:

  • 歡迎頁面
  • 使用者列表
  • 使用者新增
  • 使用者修改
  • 使用者刪除

所有的 service 使用模擬的資料。

說幹咱就幹。

結合 ng-zorro

angular 比較流行的 ui 框架有:

  • Angular Material 官方指定 UI 框架
  • NG-ZORRO,又名 Ant Design of Angular 國內比較流行的 UI 框架

Ant Design 相信做前端開發的人兒都比較熟悉了。所以這裡我們結合 NG-ZORRO 這個框架來做。如果熟悉 Vue 或者 React 版本的 Ant Design,相信你可以無縫連結啊~

1.png

我們重新使用 angular-cli 生成一個專案 ng-zorro

新增 ng-zorro 是很簡單的事情:進入 ng-zorro 根目錄,執行 ng add ng-zorro-antd 即可。

當然你也可以執行 npm install ng-zorro-antd 新增,不推薦。

結合 ng-zorro 完成之後,我們執行專案起來 npm run start,你會在 http://localhost:4200 的頁面看到下圖內容。

2.png

Not Bad, Bro.

設定路由

我們改成 hash 路由,並新增使用者路由,腳手架都幫我們完事了,我們只要做點小修改。

思路:

  • 先新增頁面 user 使用者的列表頁面,使用 ng-zorrotable 元件

  • 使用者的新增和更改頁面可以共用同一個頁面,使用 ng-zorroform 元件

  • 頁面刪除功能直接使用彈窗提示,使用 ng-zorromodal 元件

  • ng-zorro 元件按需引入

  • 調整路由檔案

按照思路,我們得在 ng-zorro 引入:

// app.module.ts

import { ReactiveFormsModule } from '@angular/forms';
import { NzTableModule } from 'ng-zorro-antd/table';
import { NzModalModule } from 'ng-zorro-antd/modal';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzFormModule } from 'ng-zorro-antd/form';
import { NzInputModule } from 'ng-zorro-antd/input';


// ...

imports: [ // 是在 imports 中新增,而不是 declarations 中宣告
  NzTableModule,
  NzModalModule,
  NzButtonModule,
  NzFormModule,
  ReactiveFormsModule,
  NzInputModule
],

簡單易理解原則,我們這裡不使用 children 進行路由的巢狀:

// app.routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
import { WelcomeComponent } from './pages/welcome/welcome.component';
import { UserComponent } from './pages/user/user.component';
import { UserInfoComponent } from './pages/user/user-info/user-info.component';

// 相關的路由
const routes: Routes = [
  { 
    path: '', 
    pathMatch: 'full', 
    redirectTo: '/welcome' 
  },
  {
    path: 'welcome',
    component: WelcomeComponent
  },
  {
    path: 'user',
    component: UserComponent
  },
  {
    path: 'user/add',
    component: UserInfoComponent
  },
  {
    path: 'user/edit/:uuid',
    component: UserInfoComponent
  }
];

@NgModule({
  imports: [RouterModule.forRoot(
    routes,
    {
      useHash: true,// 使用 hash 模式
      preloadingStrategy: PreloadAllModules
    }
  )],
  exports: [RouterModule]
})
export class AppRoutingModule { }

更改選單

使用腳手架生成的選單與我們需要開發的功能不符合,我們來調整下。

// app.component.html

<nz-layout class="app-layout">
  <nz-sider class="menu-sidebar"
            nzCollapsible
            nzWidth="256px"
            nzBreakpoint="md"
            [(nzCollapsed)]="isCollapsed"
            [nzTrigger]="null">
    <div class="sidebar-logo">
      <!-- 預設點選 logo 跳轉到首頁 -->
      <a routerLink="/welcome">
        <img src="https://ng.ant.design/assets/img/logo.svg" alt="logo">
        <h1>Ng-Zorro</h1>
      </a>
    </div>
    <ul nz-menu nzTheme="dark" nzMode="inline" [nzInlineCollapsed]="isCollapsed">
      <li nz-submenu nzOpen nzTitle="使用者管理" nzIcon="dashboard">
        <ul>
          <li nz-menu-item nzMatchRouter>
            <a routerLink="/user">使用者列表</a>
          </li>
        </ul>
      </li>
    </ul>
  </nz-sider>
  <nz-layout>
    <nz-header>
      <div class="app-header">
        <span class="header-trigger" (click)="isCollapsed = !isCollapsed">
            <i class="trigger"
               nz-icon
               [nzType]="isCollapsed ? 'menu-unfold' : 'menu-fold'"
            ></i>
        </span>
      </div>
    </nz-header>
    <nz-content>
      <div class="inner-content">
        <router-outlet></router-outlet>
      </div>
    </nz-content>
  </nz-layout>
</nz-layout>

選單展示,如果我們需要做許可權管理的話,是需要後端配合進行傳值的,然後我們再把相關的許可權選單渲染到頁面

替換成上面的程式碼後,得到的基本骨架如下:

3.png

完成使用者列表

接下來完成使用者列表的骨架,因為使用了 UI 框架,我麼寫起來異常的方便:

獲取使用者列表

// user.component.html

<nz-table #basicTable [nzData]="list">
  <thead>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody>
    <!-- 對獲取到的資料進行遍歷 -->
    <tr *ngFor="let data of basicTable.data">
      <td>{{data.name}}</td>
      <td>{{data.position}}</td>
      <td>
        <a style="color: #f00;">Delete</a>
      </td>
    </tr>
  </tbody>
</nz-table>

我們模擬了些資料在 assets 資料夾中 user.json:

{
  "users": [
    {
      "uuid": 1,
      "name": "Jimmy",
      "position": "Frontend"
    },
    {
      "uuid": 2,
      "name": "Jim",
      "position": "Backend"
    }
  ],
  "environment": "development"
}

編寫好服務之後,我們呼叫獲取使用者的資料:

// user.component.ts

import { Component, OnInit } from '@angular/core';
import { UserService } from 'src/app/services/user.service';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.scss']
})
export class UserComponent implements OnInit {

  public list: any = []

  constructor(
    private readonly userService: UserService
  ) { }

  ngOnInit(): void {
    if(localStorage.getItem('users')) {
      let obj = localStorage.getItem('users') || '{}'
      this.list =  JSON.parse(obj)
    } else {
      this.getList()
    }
  }

  // 獲取使用者列表
  getList() {
    this.userService.getUserList().subscribe({
      next: (data: any) => {
        localStorage.setItem('users', JSON.stringify(data.users))
        this.list = data.users
      },
      error: (error: any) => {
        console.log(error)
      }
    })
  }

}

因為沒有引入後端服務,這裡我們採用 localstorage 的方式記錄狀態。

上面完成後,我們得到列表資訊如下:

4.png

新增使用者和編輯使用者

我們簡單建立個表單,裡面含有的欄位就兩個,分別是 nameposition。這兩個功能是公用一個表單的~

我們在 html 中新增:

// user-info.component.html

<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()">
  <nz-form-item>
    <nz-form-control nzErrorTip="請輸入使用者名稱!">
      <input type="text" nz-input formControlName="username" placeholder="請輸入使用者名稱" style="width: 160px;" />
    </nz-form-control>
  </nz-form-item>
  <nz-form-item>
    <nz-form-control nzErrorTip="請輸入職位!">
      <input type="text" nz-input formControlName="position" placeholder="請輸入職位" style="width: 160px;"/>
    </nz-form-control>
  </nz-form-item>
  <button nz-button class="login-form-button login-form-margin" [nzType]="'primary'">確認</button>
</form>

頁面長這樣子:

5.png

然後就是邏輯的判斷,進行新增或者是修改。如果是連線帶上 uuid 的標識,就表示是編輯,show you the codes

// user-info.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, ParamMap } from '@angular/router';

@Component({
  selector: 'app-user-info',
  templateUrl: './user-info.component.html',
  styleUrls: ['./user-info.component.scss']
})
export class UserInfoComponent implements OnInit {

  public isAdd: boolean = true;
  public userInfo: any = []
  public uuid: number = 0;

  validateForm!: FormGroup;

  constructor(
    private fb: FormBuilder,
    private route: ActivatedRoute,
  ) { }

  ngOnInit(): void {
    this.userInfo = JSON.parse(localStorage.getItem('users') || '[]')
    this.route.paramMap.subscribe((params: ParamMap)=>{
      this.uuid = parseInt(params.get('uuid') || '0')
    })
    // 是編輯狀態,設定標誌符
    if(this.uuid) {
      this.isAdd = false
    }
    
    if(this.isAdd) {
      this.validateForm = this.fb.group({
        username: [null, [Validators.required]],
        position: [null, [Validators.required]]
      });
    } else {
      let current = (this.userInfo.filter((item: any) => item.uuid === this.uuid))[0] || {}
      // 資訊回填
      this.validateForm = this.fb.group({
        username: [current.name, [Validators.required]],
        position: [current.position, [Validators.required]]
      })
    }
    
  }

  submitForm() {
    // 如果不符合提交,則報錯
    if(!this.validateForm.valid) {
      Object.values(this.validateForm.controls).forEach((control: any) => {
        if(control?.invalid) {
          control?.markAsDirty();
          control?.updateValueAndValidity({ onlySelf: true });
        }
      })
      return
    }

    // 獲取到表單的資料
    const data = this.validateForm.value
    // 新增使用者
    if(this.isAdd) {
      
      let lastOne = (this.userInfo.length > 0 ? this.userInfo[this.userInfo.length-1] : {});
      this.userInfo.push({
        uuid: (lastOne.uuid ? (lastOne.uuid + 1) : 1),
        name: data.username,
        position: data.position
      })
      localStorage.setItem('users', JSON.stringify(this.userInfo))
    } else { // 編輯使用者,更新資訊
      let mapList = this.userInfo.map((item: any) => {
        if(item.uuid === this.uuid) {
          return {
            uuid: this.uuid,
            name: data.username,
            position: data.position
          }
        }
        return item
      })
      localStorage.setItem('users', JSON.stringify(mapList))
    }
  }

}

我們先設定一個標誌符 isAdd,預設是新建使用者;當 uuid 存在的時候,將其設定為 false 值,表示是編輯的狀態,對內容進行表單的回填。提交表單的操作也是按照該標誌符進行判斷。我們直接對 localStorage 的資訊進行變更,以保證同步列表資訊。

刪除功能

我們引入模態對話方塊進行詢問是否刪除。

// user.component.ts

// 刪除
delete(data: any) {
  this.modal.confirm({
    nzTitle: '<i>你想刪除該使用者?</i>',
    nzOnOk: () => {
      let users = JSON.parse(localStorage.getItem('users') || '[]');
      let filterList = users.filter((item: any) => item.uuid !== data.uuid);
      localStorage.setItem('users', JSON.stringify(filterList));
      this.list = filterList
    }
  });
}

6.png

我們找到刪除的資料,將其剔除,重新快取新的使用者資料,並更新 table 的使用者列表資料。

So,到此為止,我們順利完成了一個簡單的專案。我們用 Gif 圖整體來看看。

7.gif

【完】

更多程式設計相關知識,請存取:!!

以上就是Angular + NG-ZORRO快速開發一個後臺系統的詳細內容,更多請關注TW511.COM其它相關文章!