README.md

    目前为止Angular版本是11,利用TypeScript的装饰器(Decorators)特性,可以写类似Java Spring Boots面向切面风格的代码。没写过这样代码的人可能会不适应,其实基础好的话稍微看看官方文档可以马上上手。

    项目介绍

    本项目使用脚手架 Angular CLI (version 11.2.12) 构建。UI使用 NG-ZORRO (官网),这是 Ant Design 的 Angular 版。

    目前只实现纯静态登陆。用户名: admin 密码: 123456

    截图:

    1. 默认登陆界面


    2. 点击登陆按钮验证表单非空


    3. 验证用户名密码错误


    4. 登陆成功


    项目目录

    ng-demo
    ├── README.md
    ├── angular.json
    ├── e2e
       ├── protractor.conf.js
       ├── src
          ├── app.e2e-spec.ts
          └── app.po.ts
       └── tsconfig.json
    ├── karma.conf.js
    ├── package.json
    ├── src
       ├── app
          ├── app-routing.module.ts
          ├── app.component.html
          ├── app.component.scss
          ├── app.component.spec.ts
          ├── app.component.ts
          ├── app.module.ts
          └── components
              ├── home
                 ├── home.component.html
                 ├── home.component.scss
                 └── home.component.ts
              ├── login
                 ├── login.component.html
                 ├── login.component.scss
                 ├── login.component.ts
                 └── login.module.ts
              └── ng-zorro-antd.module.ts
       ├── assets
          └── images
       ├── environments
          ├── environment.prod.ts
          └── environment.ts
       ├── favicon.ico
       ├── index.html
       ├── main.ts
       ├── polyfills.ts
       ├── styles.scss
       ├── test.ts
       └── theme.less
    ├── tsconfig.app.json
    ├── tsconfig.json
    ├── tsconfig.spec.json
    └── tslint.json

    项目说明

    /src/app/app.modules.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { LoginModule } from './components/login/login.module';
    import { NZ_I18N } from 'ng-zorro-antd/i18n';
    import { zh_CN } from 'ng-zorro-antd/i18n';
    import { registerLocaleData } from '@angular/common';
    import zh from '@angular/common/locales/zh';
    import { FormsModule, ReactiveFormsModule } from '@angular/forms';
    import { HttpClientModule } from '@angular/common/http';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
    
    registerLocaleData(zh);
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        AppRoutingModule,
        LoginModule,
        FormsModule,
        HttpClientModule,
        BrowserAnimationsModule,
        ReactiveFormsModule
      ],
      providers: [{ provide: NZ_I18N, useValue: zh_CN }],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    • 引入路由模块 AppRoutingModule、登陆模块 LoginModule 、表单模块 FormsModule ,并通过 @NgModule 装饰器的 imports 属性导入。
    • AppComponent 组件放在 @NgModule 装饰器的 declarations 属性 (可声明对象表) 和 bootstrap 属性 (主视图,只有根模块才设置这个属性) 中。
    • 关于 @NgModule 的使用,参考官方文档模块部分

    /src/app/app.component.html

    <router-outlet></router-outlet>

    只有一个路由标签。

    /src/app/app.routing.module.ts

    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    
    import { LoginComponent } from './components/login/login.component';
    import { HomeComponent } from './components/home/home.component';
    
    const routes: Routes = [
      {path: 'login', component: LoginComponent},
      {path: '', redirectTo: '/login', pathMatch: 'full'},
      {path: 'home', component: HomeComponent},
    ];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
    • 设置路由的文件,项目启动后页面默认重定向到 /login 路由。
    • 添加了 /home 路由,本实例暂时没用到。

    /src/app/components/ng-zorro-antd.module.ts

    ...
    import { NzButtonModule } from 'ng-zorro-antd/button';
    ...
    @NgModule({
      exports: [
        ...
        NzButtonModule,
        ...
      ]
    })
    export class NgZorroAntdModule {}
    • 这个文件从 ng-zorro-antd 中取得所有组件 Module 并通过@NgModule 装饰器的 exports 属性导出。

    /src/app/components/login/login.moudle.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { LoginComponent } from './login.component';
    import { NgZorroAntdModule } from '../ng-zorro-antd.module';
    import { FormsModule, ReactiveFormsModule } from '@angular/forms';
    
    @NgModule({
      declarations: [
      	LoginComponent
      ],
      imports: [
        BrowserModule,
        NgZorroAntdModule,
        FormsModule,
        ReactiveFormsModule
      ],
      providers: [],
      bootstrap: [
      	LoginComponent
      ]
    })
    export class LoginModule { }
    • 这里引入了刚才定义的 ng-zorro-antd 导出的模块 NgZorroAntdModule,可用在 html 部分,例如一个普通按钮 <button nz-button>按钮</button> 标签, 增加了 nz-button 属性,让它在编译之后称为 ng-zorro-antd 按钮组件。
    • 引入 AppComponent 组件。
    • 注意引入表单相关依赖,做表单校验等会用到。

    /src/app/components/login/login.components.html 登陆的 html 部分只列出表单相关代码。

    ...
      <form nz-form name="form" [formGroup]="validateForm" (ngSubmit)="onSubmit()">
        <nz-form-item>
          <nz-form-label [nzSpan]="4">用户名</nz-form-label>
          <nz-form-control 
            nzHasFeedback 
            [nzSpan]="20"
            nzErrorTip="请输入用户名"
          >
            <nz-input-group [nzSuffix]="suffixUsername">
              <input 
                nz-input 
                placeholder="请输入用户名" 
                name="username" 
                formControlName="username"
                required 
              />
            </nz-input-group>
            <ng-template #suffixUsername>
              <i 
                nz-icon 
                class="ant-input-clear-icon" 
                nzTheme="fill" 
                nzType="close-circle" 
                *ngIf="validateForm.controls.username.value.length>0" 
                (click)="validateForm.controls.username.setValue('')"
              ></i>
            </ng-template>
    
          </nz-form-control>
        </nz-form-item>
        <nz-form-item>
          <nz-form-label [nzSpan]="4">&nbsp;&nbsp;&nbsp;&nbsp;</nz-form-label>
          <nz-form-control 
            nzHasFeedback 
            [nzSpan]="20"
            nzErrorTip="请输入密码"
          >
            <nz-input-group [nzSuffix]="suffixPassword">
              <input 
                nz-input 
                name="password" 
                formControlName="password"
                [type]="passwordVisible ? 'text' : 'password'" 
                placeholder="请输入密码" 
                required
              />
            </nz-input-group>
            <ng-template #suffixPassword>
              <i 
                nz-icon 
                class="ant-input-clear-icon" 
                nzTheme="fill" 
                nzType="close-circle" 
                *ngIf="validateForm.controls.password.value.length>0" 
                (click)="validateForm.controls.password.setValue('')"
              ></i>
              <i 
                nz-icon 
                [nzType]="passwordVisible ? 'eye-invisible' : 'eye'" 
                (click)="passwordVisible = !passwordVisible"
              ></i>
            </ng-template>
          </nz-form-control>
        </nz-form-item>
        <nz-form-item>
          <nz-form-control [nzSpan]="20" [nzOffset]="4">
            <div nz-row class="login-form-margin">
              <div nz-col [nzSpan]="12">
                <label nz-checkbox formControlName="remember">
                  <span>记住我</span>
                </label>
              </div>
              <div nz-col [nzSpan]="12" style="text-align: right;">
                <a class="login-form-forgot">忘记密码?</a>
              </div>
            </div>
          </nz-form-control>
        </nz-form-item>
        <nz-form-item>
          <nz-form-control [nzSpan]="24" [nzOffset]="0" style="text-align: center;">
            <button 
              type="submit"
              nz-button 
              style="width: 100px;" 
              nzType="primary"
              ng-disabled="form.$invalid"
            >登录</button>
          </nz-form-control>
        </nz-form-item>
      </form>
    ...
    • 表单的 [formGroup]="validateForm" 属性绑定验证对象。
    • 表单的 (ngSubmit)="onSubmit()" 属性绑定表单提交事件。
    • 输入控件的 formControlName 属性绑定对应的控件名。

    /src/app/components/login/login.components.ts

    import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import { NzMessageService } from 'ng-zorro-antd/message';
    
    @Component({
      selector: 'app-component',
      templateUrl: './login.component.html',
      styleUrls: ['./login.component.scss']
    })
    export class LoginComponent implements OnInit {
    
      constructor(
        public login: FormBuilder,
        private message: NzMessageService
      ) {}
      
      public validateForm!: FormGroup;
      public passwordVisible:Boolean = false;
      
      // 提交表单
      onSubmit():void{
    
        // 更新表单未通过验证的控件高亮显示
        for (const i in this.validateForm.controls) {
          this.validateForm.controls[i].markAsDirty();
          this.validateForm.controls[i].updateValueAndValidity();
        }
    
        // 如果验证通过
        if(this.validateForm.status=='INVALID'){
          this.message.create('warning', '请填写用户名和密码');
          return;
        }
    
        // 如果验证通过
        if(this.validateForm.status=='VALID'){
          let { username, password } = this.validateForm.value;
          if( username == 'admin' && password == '123456' ){
            this.message.create('success', '登录成功');
          }else{
            this.message.create('error', '用户名密码错误');
          }
        }
      }
    
      // 初始化
      ngOnInit(): void {
        this.validateForm = this.login.group({
          username: ['', [Validators.required]],
          password: ['', [Validators.required]],
          remember: [true]
        });
      }
    }
    • ngOnInit() 是组件生命周期的一种,Angular 会在首次检查完组件或指令的输入属性后,紧接着调用它。这里的业务逻辑是初始化验证表单的内容。
    • onSubmit() 提交表单的逻辑。首先验证实现了 FormGroup 接口的表单。高亮化未通过验证的组件(用户名和密码只做了非空验证)。然后验证是否登陆成功,做对应处理。

    项目简介

    Angular + NG-ZORRO Demo

    发行版本

    当前项目没有发行版本

    贡献者 1

    sonicwater @sonicwater1

    开发语言

    • TypeScript 67.4 %
    • HTML 19.3 %
    • JavaScript 9.7 %
    • SCSS 2.2 %
    • Less 1.4 %