Cet article partagera avec vous une application pratique de Angular pour apprendre à développer rapidement un système backend en utilisant angualr combiné avec ng-zorro. J'espère que cela sera utile à tout le monde !
Ces derniers jours, nous avons beaucoup appris sur angular
, et cette fois nous avons un petit produit fini. angular
的知识点了,这次我们来个小成品。
angualr
结合 ng-zorro
快速且规范的开发一个后台系统。【相关教程推荐:《angular教程》】
系统功能包括下面的内容:
所有的 service 使用模拟的数据。
说干咱就干。
结合 ng-zorro
angular
比较流行的 ui
框架有:
Ant Design
相信做前端开发的人儿都比较熟悉了。所以这里我们结合 NG-ZORRO
这个框架来做。如果熟悉 Vue
或者 React
版本的 Ant Design
,相信你可以无缝链接啊~
我们重新使用 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
的页面看到下图内容。
Not Bad, Bro.
配置路由
我们改成 hash
路由,并添加用户路由,脚手架都帮我们完事了,我们只要做点小修改。
思路:
先添加页面 user
用户的列表页面,使用 ng-zorro
中 table
组件
用户的新增和更改页面可以共用同一个页面,使用 ng-zorro
中 form
组件
页面删除功能直接使用弹窗提示,使用 ng-zorro
中 modal
组件
对 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>
菜单展示,如果我们需要做权限管理的话,是需要后端配合进行传值的,然后我们再把相关的权限菜单渲染到页面
替换成上面的代码后,得到的基本骨架如下:
完成用户列表
接下来完成用户列表的骨架,因为使用了 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
的方式记录状态。
上面完成后,我们得到列表信息如下:
新增用户和编辑用户
我们简单建立个表单,里面含有的字段就两个,分别是 name
和 position
。这两个功能是公用一个表单的~
我们在 html
angualr
se combine avec ng-zorro
pour développer rapidement et de manière standardisée un système backend. [Recommandations de didacticiel associées : "Tutoriel angulaire
"]Les fonctions du système incluent les éléments suivants :
angular
Le ui
le plus populaire code > Les frameworks incluent : 🎜NG-ZORRO
. Si vous connaissez la version Vue
ou React
de Ant Design
, je pense que vous pouvez vous connecter de manière transparente~🎜🎜🎜🎜Nous réutilisons angular-cli </code > Générer un projet <code>ng-zorro
. 🎜🎜Ajouter ng-zorro
est très simple : entrez dans le répertoire racine ng-zorro
et exécutez ng add ng-zorro-antd
. 🎜🎜Bien sûr, vous pouvez également exécuter npm install ng-zorro-antd
pour l'ajouter, mais ce n'est pas recommandé. 🎜
🎜Combiné avec ng-zorro
Une fois terminé, nous exécutons le projet npm run start
, vous serez sur http://localhost:4200
code> page, voir l'image suivante. 🎜🎜🎜🎜< strong>Pas mal, frérot.🎜🎜Configuration du routage🎜🎜Nous l'avons changé en hash< /code> routage, et ajouter le routage utilisateur, l'échafaudage l'a fait pour nous, nous n'avons besoin que de quelques modifications mineures. 🎜🎜Idée : 🎜<ul style="list-style-type: disc;"><li>🎜Ajoutez d'abord la page <code>user
à la page de liste des utilisateurs, utilisez ng-zorro</code > Dans le composant <code>table
🎜ng-zorro
dans le formulaire
> composant🎜modal
dans ng-zorro
🎜ng-zorro
selon les besoins🎜ng-zorro
introduit : 🎜// 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>
enfants
ici pour l'imbrication des itinéraires : 🎜// 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)) } } }
// 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 } }); }
🎜Affichage du menu, si nous devons gérer les autorisations, nous avons besoin que le backend coopère avec le transfert de valeur, puis nous afficherons le menu d'autorisation correspondant sur la page🎜🎜Après l'avoir remplacé par Avec le code ci-dessus, le squelette de base obtenu est le suivant : 🎜🎜🎜🎜Complétez la liste des utilisateurs🎜🎜Ensuite, complétez le squelette de la liste des utilisateurs , parce que le framework
UI est utilisé
, il est extrêmement pratique pour nous d'écrire : 🎜🎜Obtenir la liste des utilisateurs🎜rrreee🎜Nous avons simulé certaines données dans les assets</strong> code> dossier <code>user .json
:🎜rrreee🎜Après avoir écrit le service, nous appelons pour obtenir les données de l'utilisateur :🎜rrreee🎜Comme aucun service back-end n'est introduit, nous utilisons ici localstorage< /code> pour enregistrer l’état. 🎜🎜Après avoir complété ce qui précède, nous obtenons les informations de la liste comme suit : 🎜🎜<img src="https://img.php.cn/upload/image/234/426/447/1650508770904440.png" title="1650508770904440 .png" alt="Angular + NG-ZORRO développent rapidement un système backend"/>🎜🎜<strong>Ajouter des utilisateurs et modifier des utilisateurs</strong>🎜🎜Nous créons simplement un formulaire qui ne contient que deux champs, à savoir <code>nom
et position
. Ces deux fonctions partagent un formulaire~🎜🎜On ajoute en html
:🎜rrreee🎜La page ressemble à ceci :🎜🎜🎜🎜然后就是逻辑的判断,进行添加或者是修改。如果是连接带上 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 } }); }
我们找到删除的数据,将其剔除,重新缓存新的用户数据,并更新 table
的用户列表数据。
So,到此为止,我们顺利完成了一个简单的项目。我们用 Gif
图整体来看看。
【完】
更多编程相关知识,请访问:编程入门!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!