¡Acostúmbrate a escribir juntos! Este es el séptimo día de mi participación en el "Nuggets Daily New Plan·Desafío de actualización de abril", haz clic para ver los detalles del evento
En los últimos días de artículos, hemos aprendido muchos puntos angular
de conocimiento, esta vez tenemos un pequeño producto terminado.
angualr
Combinado con el desarrollo ng-zorro
rápido y estandarizado de un sistema backend.
Las funciones del sistema incluyen lo siguiente:
- pagina de bienvenida
- Lista de usuarios
- Usuario agregado
- Modificación de usuario
- Eliminar usuario
Todos los servicios utilizan datos simulados.
Vamos a hacerlo.
Combinar ng-zorro
angular
Los ui
marcos son:
- Material angular designado oficialmente marco de interfaz de usuario
- NG-ZORRO, también conocido como Ant Design of Angular, es un marco de interfaz de usuario popular en China
Ant Design
Creo que las personas que hacen desarrollo front-end están más familiarizadas con él. Así que aquí combinamos NG-ZORRO
este marco para hacerlo. Si está familiarizado Vue
con la React
versión Ant Design
, creo que puede vincular sin problemas ~
Reutilizamos angular-cli
para generar un proyecto ng-zorro
. Si no conoce el contenido angular
principal , vaya al artículo para comprender el contenido del desarrollo angular .
Agregar ng-zorro
es un asunto muy simple: vaya al ng-zorro
directorio ng add ng-zorro-antd
raíz .
Por supuesto, también puede realizar
npm install ng-zorro-antd
add , lo cual no se recomienda.
ng-zorro
Una vez completada la combinación , ejecutamos el proyecto npm run start
y verá el siguiente contenido en http://localhost:4200
la página de .
No está mal, hermano.
Configurar enrutamiento
我们改成 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
中添加:
// 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>
复制代码
页面长这样子:
Luego está el juicio lógico, agregando o modificando. Si es uuid
el , significa edición 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))
}
}
}
复制代码
Primero establecemos un identificador isAdd
, el predeterminado es crear un nuevo usuario; cuando uuid
exista , configúrelo en el false
valor, indicando que está en estado de edición, y rellene el contenido del formulario. La operación de envío del formulario también se juzga según este identificador. Realizamos cambios directamente en localStorage
la información para mantener sincronizada la información del listado.
borrar función
Introducimos un cuadro de diálogo modal para preguntar si desea eliminar.
// 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
}
});
}
复制代码
Encontramos los datos eliminados, los seleccionamos, recuperamos los nuevos datos de usuario y actualizamos table
los datos de la lista de usuarios.
Entonces, hasta ahora, hemos completado con éxito un proyecto simple. Echemos un vistazo a la Gif
gráfica como un todo.
【Fin】✅