首页 > 其他分享 >Angular 18 上手开发

Angular 18 上手开发

时间:2024-11-01 15:34:44浏览次数:3  
标签:... 18 app hello component ts angular 开发 Angular

0x01 概述

(1)简介

  • 官方网站:https://www.angular.cn/
  • Angular 由 Google 的专业团队维护,Angular 提供了广泛的工具、API 和库,简化和优化开发工作流程
  • Angular 提供了一个坚实的平台,可用于构建快速、可靠、能够随着团队规模和代码库规模扩展的应用程序
  • 特点:
    • 整合性高,降低技术决策成本
    • 简化 DOM 操作,注重业务逻辑
    • 采用后端的依赖注入系统
  • 与 React、Vue 对比,Angular:
    • 在大型企业级应用中提供更成熟的框架和严格的架构模式,适合复杂项目的长期维护
    • 初始加载时间较长,不够灵活和轻量
    • 学习曲线较陡峭

(2)创建项目

Angular 18 于 2024 年 5 月正式发布,以下内容均采用 18.2.10 / 18.2.9 版本,NodeJS 采用 23.0.0 版本,npm 采用 10.9.0

  1. 使用命令 npm install -g @angular/cli 安装脚手架
  2. 使用命令 ng new angular-app 创建名为 angular-app 的项目
    1. 不向 Google 发送数据
    2. 不使用 CSS 预编译
    3. 不使用 SSR
  3. 使用命令 cd angular-app 进入项目目录
  4. 使用命令 ng serve --open 启动项目并自动开启浏览器

使用 ng 命令创建组件等:

脚手架 说明 命令
Component 组件 ng generate component my-new-component
Directive 指令 ng generate directive my-new-directive
Pipe 管道 ng generate pipe my-new-pipe
Service 服务 ng generate service my-new-service
Class ng generate class my-new-class
Interface 接口 ng generate interface my-new-interface
Enum 枚举 ng generate enum my-new-enum
Module 模块 ng generate module my-new-module

(3)项目结构

  • .angular:编译缓存目录

  • node_modules:Node 包目录

  • public:公共资源目录

  • src:代码资源目录

    • app:App 模块代码目录

      • app.component.css:组件样式文件
      • app.component.html:组件模板文件
      • app.component.spec.ts:组件测试文件
      • app.component.ts:组件入口文件
      • app.config.ts:模块配置文件
      • app.routes.ts:模块路由文件
    • index.html:模板文件

      <!doctype html>
      <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>AngularApp</title>
        <base href="/">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" type="image/x-icon" href="favicon.ico">
      </head>
      <body>
        <app-root></app-root>
      </body>
      </html>
      
    • main.ts:入口文件

      import { bootstrapApplication } from '@angular/platform-browser';
      import { appConfig } from './app/app.config';
      import { AppComponent } from './app/app.component';
      
      bootstrapApplication(AppComponent, appConfig)
        .catch((err) => console.error(err));
      
    • style.css:全局样式文件

  • .editorconfig:编辑器配置文件,详情参考 https://editorconfig.org

  • .gitignore:git 忽略文件

  • angular.json:Angular 配置文件

  • package.json:Node 包配置文件

    • "script" 项中添加以下内容:

      {
        "scripts": {
          "dev": "ng serve --open",
          // ...
        },
      }
      

      以后通过命令 npm run dev 来启动项目(代替命令 ng serve --open

  • tsconfig.json:TypeScript 配置文件

flowchart TB 项目-->模块1 & 模块2 & m[...] & 模块n 模块1-->组件1 & 组件2 & c[...] & 组件n

0x02 组件

(1)简介

以 app.component.ts 为例:

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
title = 'angular-app';
}
  • @Component 是一个装饰器,用于加载一些配置信息,其中

    • selector:选择器,用于选择模板中的 DOM 标签,并将该组件渲染至该标签中

      <!-- filename: index.html -->
      <body>
        <app-root></app-root>
      </body>
      
    • standalone:独立模式,true 表示该组件不依赖于任何模块,可以直接在应用中使用,而不需要通过模块进行声明

    • imports:导入组件,此处导入了 RouterOutlet 组件

      • RouterOutlet 是 Angular 路由模块中的一个重要组件,用于在应用中定义路由视图的占位符

        类似 React Router 中的 <Outlet />

    • templateUrl:模板文件路径

    • styleUrl:样式文件路径

  • 导出经过装饰器声明的类,类中可以传值

(2)创建组件

  1. 使用命令 ng generate component hello(或 ng g c hello)创建一个在 app 目录下,名为 hello 的新组件

  2. app 目录结构

    flowchart TB app-->hello & app.component.css & app.component.html & ... hello-->hello.component.css & hello.component.html & hello.component.spec.ts & hello.component.ts
  3. 修改 hello.component.html

    <div style="width: 200px; height: 200px; background-color: red">
      这里是 hello 组件
    </div>
    
  4. 修改 hello.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-hello',
      standalone: true,
      imports: [],
      templateUrl: './hello.component.html',
      styleUrl: './hello.component.css'
    })
    export class HelloComponent {
    
    }
    
  5. 修改 app.component.ts

    import { HelloComponent } from "./hello/hello.component";
    
  6. 修改 app.component.html

    <app-hello></app-hello>
    
  7. 启动项目,访问 http://localhost:4200/,此时可以发现页面中存在 hello 组件

(3)生命周期

  • 生命周期钩子及其执行顺序如下:

    钩子 作用 时机
    ngOnChanges() 每当 Angular 设置或重新设置数据绑定的输入属性时响应 ngOnInit() 之前以及所绑定的一个或多个输入属性方式变化时调用
    ngOnInit() 在 Angular 第一次显示数据绑定和设置指令或组件的输入属性后,初始化指令或组件 首次 ngOnChanges() 之后调用,且仅调用一次
    ngDoCheck() 每当发生 Angular 无法或不愿自检的变化时,进行检测 每次执行变更检测时的 ngOnChanges() 之后调用
    首次执行变更检测的 ngOnInit() 之后调用
    ngAfterContentInit() 当 Angular 将外部内容投影至组件或指令中的内容之后调用 首次 ngDoCheck() 之后调用,且仅调用一次
    ngAfterContentChecked() 每当 Angular 检测完被投影至组件或指令中的内容之后调用 每次 ngDoCheck() 之后调用
    首次 ngAfterContentInit() 之后调用
    ngAfterViewInit() 当 Angular 初始化完组件视图、其子视图、或包含该指令的视图之后调用 首次 ngAfterContentChecked() 之后调用,且仅调用一次
    ngAfterViewChecked() 每当 Angular 检测完组件视图、其子视图、或包含该指令的视图的变更之后调用 每次 ngAfterContentChecked() 之后调用
    首次 ngAfterViewInit() 之后调用
    ngOnDestroy() 每当 Angular 销毁指令或组件之前调用 在 Angular 销毁指令或组件之前立即调用
    graph LR ngOnChanges--首次-->ngOnInit-->ngDoCheck--首次-->ngAfterContentInit-->ngAfterContentChecked--首次-->ngAfterViewInit-->ngAfterViewChecked-.->ngOnDestroy ngOnChanges-->ngDoCheck-->ngAfterContentChecked-->ngAfterViewChecked
  • 举例:app.component.ts

    export class AppComponent {
      ngOnChanges() {
        console.log('ngOnChanges');
      }
      ngOnInit() {
        console.log('ngOnInit');
      }
      ngDoCheck() {
        console.log('ngDoCheck');
      }
      ngAfterContentInit() {
        console.log('ngAfterContentInit');
      }
      ngAfterContentChecked() {
        console.log('ngAfterContentChecked');
      }
      ngAfterViewInit() {
        console.log('ngAfterViewInit');
      }
      ngAfterViewChecked() {
        console.log('ngAfterViewChecked');
      }
      ngOnDestroy() {
        console.log('ngOnDestroy');
      }
    }
    

(4)交互

组件间传参

  • @Input:用于父组件给子组件绑定属性,设置输入类数据

    1. hello.component.ts

      import { Component, Input } from '@angular/core';
      
      @Component({/* ... */})
      export class HelloComponent {
        @Input() username!: string;
      
        ngOnInit() {
          console.log(this.username);
        }
      }
      
      
    2. app.component.html

      <app-hello [username]="'SRIGT'"></app-hello>
      
  • @Output:用于子组件弹射触发事件,该事件来自父组件给子组件的传递

    1. app.component.ts

      export class AppComponent {
        list = [1, 2, 3];
        add(newNumber: number) {
          this.list.push(newNumber);
        }
      }
      
    2. hello.component.ts

      import { Component, EventEmitter, Output } from '@angular/core';
      
      @Component({
        selector: 'app-hello',
        standalone: true,
        imports: [],
        templateUrl: './hello.component.html',
        styleUrl: './hello.component.css',
      })
      export class HelloComponent {
        @Output() add = new EventEmitter();
      
        clickHandler() {
          this.add.emit(4);
        }
      }
      
    3. app.component.html

      <app-hello (add)="add($event)"></app-hello>
      <p>{{ list.toString() }}</p>
      
    4. hello.component.html

      <button (click)="clickHandler()">+4</button>
      
  • @ViewChild:获取子组件实例与数据

    1. app.component.ts

      import { Component, ViewChild } from '@angular/core';
      // ...
      @Component({/* ... */})
      export class AppComponent {
        @ViewChild('childComp') child: any;
      
        clickHandler() {
          console.log(this.child);
        }
      }
      
    2. app.component.html

      <app-hello #childComp></app-hello>
      <button (click)="clickHandler()">Click</button>
      

0x03 模板

(1)插值

  • “插值”指将表达式嵌入到 HTML 文档中,通过 {{ }} 实现

    <!-- filename: app.component.html -->
    <p>1 + 1 = {{ 1 + 1 }}</p>
    
  • 在 app.component.ts 导出的类中包含的变量值,也可以通过插值语法嵌入到 HTML 文档中

    • app.component.ts

      // import ...
      
      @Component({/* ... */})
      export class AppComponent {
        expression = `1 + 1 = ${1 + 1}`;
      }
      
    • app.component.html

      <p>{{ expression }}</p>
      

(2)绑定

a. 属性绑定

  • 一般地,属性绑定使用 [ ] 实现,如:

    <h1 [id]="'h1-title'">Title</h1>
    

    渲染后变成了

    <h1 _ngcontent-ng-xxxxxxxxxxx id="h1-title">Title</h1>
    
  • 类绑定

    • 单一类绑定:

      <h1 [class]="'h1-title'">Title</h1>
      <!-- 或 -->
      <h1 [class.h1-title]="true">Title</h1>
      
    • 多个类绑定:

      <h1 [class]="'h1-title text-4xl font-bold'">Title</h1>
      <!-- 或 -->
      <h1 [class]="{ 'h1-title': true, 'text-4xl': false }">Title</h1>
      <!-- 或 -->
      <h1 [class]="[ 'h1-title', 'text-4xl' ]">Title</h1>
      
  • 样式绑定

    • 单一样式绑定:

      <h1 [style]="'font-size:1em'">Title</h1>
      <!-- 或 -->
      <h1 [style.font-size]="'1em'">Title</h1>
      <!-- 或 -->
      <h1 [style.font-size.em]="'1'">Title</h1>
      
    • 多重样式绑定:

      <h1 [style]="'font-size:1em;font-weight:900;'">Title</h1>
      <!-- 或 -->
      <h1 [style]="{ 'font-size': '1em', 'font-weight': 900 }">Title</h1>
      

b. 事件绑定

  • 一般地,事件绑定使用 ( ) 实现,如:

    • app.component.ts

      export class AppComponent {
        clickHandler() {
          alert("Button clicked")
        }
      }
      
    • app.component.html

      <button (click)="clickHandler()">Click</button>
      
  • 对于事件对象,使用 $event 传递

    • app.component.ts

      export class AppComponent {
        clickHandler(event: Event) {
          console.log(event)
        }
      }
      
    • app.component.html

       <button (click)="clickHandler($event)">Click</button>
      

c. 双向绑定

  • 双向绑定是应用内组件共享数据的方式

  • 一般地,双向绑定使用 [( )] 实现

    • app.component.ts

      export class AppComponent {
        number: number = 10;
      
        add() {
          this.number += 1;
        }
      
        sub() {
          this.number -= 1;
        }
      }
      
    • app.component.html

      <button (click)="sub()">-1</button>
      <button (click)="add()">+1</button>
      <span>Current number is {{ number }}</span>
      
  • 表单元素的双向绑定需要 @NgModule 装饰器,使用前需要从 @angular/forms 中导入 FormsModule

    • app.component.ts

      // ...
      import { FormsModule } from '@angular/forms';
      
      @Component({
        // ...
        imports: [/*...*/, FormsModule],
      })
      export class AppComponent {
        text = '';
      }
      
    • app.component.html

      <input [(ngModel)]="text" />
      <p>Input text: {{ text }}</p>
      

d. 模板变量

  • 模板变量使用 # 声明

    • app.component.ts

      export class AppComponent {
        clickHandler(value: string) {
          alert(value);
        }
      }
      
    • app.component.html

      <input #text />
      <button (click)="clickHandler(text.value)">Submit</button>
      
  • Angular 根据声明模板变量的位置进行赋值

    • 在标准 HTML 元素上,则引用该元素
    • 在组件上,则引用该组件实例
    • <ng-template> 元素上,则引用一个 TemplateRef 实例来代表模板

(3)渲染

a. 条件

I. if

使用 *ngIF 实现,使用前需要从 @angular/common 导入 NgIf

注意:仅用于元素是否被渲染,而非控制元素的显隐

  • app.component.ts

    // ...
    import { NgIf } from '@angular/common';
    
    @Component({
      // ...
      imports: [/* ... */, NgIf],
    })
    export class AppComponent {
      isRender = false;
    }
    
  • app.component.html

    <p>
      My name is
      <span *ngIf="isRender">John</span>
      <span *ngIf="!isRender">SRIGT</span>
      .
    </p>
    <!-- My name is SRIGT . -->
    

II. switch

使用 *ngSwitch 实现,使用前需要从 @angular/common 导入 NgSwitch

  • app.component.ts

    // ...
    import { NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common';
    
    @Component({
      // ...
      imports: [/* ... */, NgSwitch, NgSwitchCase, NgSwitchDefault],
    })
    export class AppComponent {
      nameType = "nickname"
    }
    
  • app.component.html

    <p [ngSwitch]="nameType">
      My name is
      <span *ngSwitchCase="'realname'">John</span>
      <span *ngSwitchCase="'nickname'">SRIGT</span>
      <span *ngSwitchDefault>Someone</span>
      .
    </p>
    <!-- My name is SRIGT . -->
    

b. 循环

循环渲染使用 *ngFor 实现,使用前需要从 @angular/common 导入 NgFor

  • app.component.ts

    // ...
    import { NgFor } from '@angular/common';
    
    @Component({
      // ...
      imports: [/* ... */, NgFor],
    })
    export class AppComponent {
      names = ['Alex', 'Bob', 'Charlie'];
    }
    
  • app.component.html

    <div *ngFor="let name of names; let i = index; let odd = odd">
      {{ odd }} {{ i }} {{ name }}
    </div>
    <!--
    false 0 Alex
    true 1 Bob
    false 2 Charlie
    -->
    

c. 控制流

Angular 16 新特性

  • @if@else if@else

    • app.component.ts

      export class AppComponent {
        isRender = false;
      }
      
    • app.component.html

      <p>
        My name is
        @if (isRender) { {{ "John" }} }
        @else { {{ "SRIGT" }} }
        .
      </p>
      <!-- My name is SRIGT . -->
      
  • @switch@case@default

    • app.component.ts

      export class AppComponent {
        nameType = "nickname"
      }
      
    • app.component.html

      <p>
        My name is
        @switch (nameType) {
          @case ('realname') {
            {{ "John" }}
          }
          @case ('nickname') {
            {{ "SRIGT" }}
          }
          @default {
            {{ "Someone" }}
          }
        }
        .
      </p>
      <!-- My name is SRIGT . -->
      
  • @for

    • app.component.ts

      export class AppComponent {
        items = [
          { id: 1, name: 'Alex' },
          { id: 2, name: 'Bob' },
          { id: 3, name: 'Charlie' },
        ];
      }
      
    • app.component.html

      <ul>
        @for (item of items; track item.id) {
        <li>{{ item.name }}</li>
        } @empty {
        <li>There are no items.</li>
        }
      </ul>
      

(4)表单

a. 单个表单控件

  1. 注册响应式表单模块,需要从 @angular/forms 导入 ReactiveFormsModule

    // ...
    import { ReactiveFormsModule } from '@angular/forms';
    
    @Component({
      // ...
      imports: [/* ... */, ReactiveFormsModule],
    })
    export class AppComponent {}
    
  2. 生成一个新的 FormControl 实例并保存在组件中,需要从 @angular/forms 导入 FormControl

    // ...
    import { FormControl, ReactiveFormsModule } from '@angular/forms';
    
    @Component({/* ... */})
    export class AppComponent {
      username = new FormControl('');
    
      reset() {
        this.username.setValue('');
      }
    }
    
  3. 在模板中注册该实例

    <label>
      username:
      <input type="text" [formControl]="username" />
    </label>
    <p>{{ username.value }}</p>
    <button (click)="reset()">reset</button>
    

b. 多个表单控件

  1. 创建 FormGroup 实例,需要从 @angular/forms 导入 FormGroup

    // ...
    import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
    
    @Component({/* ... */})
    export class AppComponent {
      loginForm = new FormGroup({
        username: new FormControl(''),
        password: new FormControl(''),
      });
    
      onSubmit() {
        alert(
          `username: ${this.loginForm.value.username}\npassword: ${this.loginForm.value.password}`
        );
      }
    }
    
  2. 在模板中注册该实例

    <form [formGroup]="loginForm">
      <label>
        username:
        <input type="text" formControlName="username" />
      </label>
      <br />
      <label>
        password:
        <input type="password" formControlName="password" />
      </label>
      <br />
      <button (click)="onSubmit()">Login</button>
    </form>
    

c. 表单验证

  • Angular 支持 HTML5 提供的表单验证关键字(如 required 等),通过双向绑定可以获取组件信息,从得到验证结果

    • app.component.ts

      // ...
      import {
        FormControl,
        FormGroup,
        ReactiveFormsModule,
        ValidationErrors,
        Validators,
      } from '@angular/forms';
      
      @Component({
        // ...
        imports: [/* ... */, ReactiveFormsModule],
      })
      export class AppComponent {
        // 表单数据
        formData = { username: '', password: '' };
        
        // 自定义验证方法
        passwordValidator(control: FormControl): ValidationErrors | null {
          return control.value.length < 5 ? { password: true } : null;
        }
      
        // 表单控件组
        loginForm = new FormGroup({
          username: new FormControl(this.formData.username, [
            Validators.maxLength(10),
          ]),
          password: new FormControl(this.formData.password, [
            Validators.required,
            this.passwordValidator,
          ]),
        });
      
        // 提交方法
        onSubmit() {
          alert(
            `username: ${this.loginForm.value.username}\npassword: ${this.loginForm.value.password}`
          );
        }
      }
      
    • app.component.html

      <form [formGroup]="loginForm">
        <label>
          username:
          <input type="text" formControlName="username" required />
        </label>
        <br />
        <span>{{ loginForm.get("username")?.valid }}</span>
        <br />
        <label>
          password:
          <input type="password" formControlName="password" />
        </label>
        <br />
        <span>{{ loginForm.get("password")?.valid }}</span>
        <br />
        <button (click)="onSubmit()">Login</button>
      </form>
      

      其中,.valid 是布尔类型

  • ngModel 可用于跟踪修改状态与有效性验证,通过三个 CSS 类来更新控件:

    状态 为真 为假
    已被访问 ng-touched ug-untouched
    已变化 ng-dirty ng-pristine
    有效 ng-valid ng-invalid
    input {
      outline: none;
    }
    
    input.ng-invalid {
      border: 1px solid red;
    }
    

(5)管道

  • 管道用于传输,即数据处理
  • 管道采用链式连接,自左向右,依次执行
  • 语法格式:{{ 输入数据 | 管道1:参数 | 管道2... }}

注意:管道操作符的优先级高于 JavaScript 三元运算符 ?:,同时使用时需要使用 ( ) 包裹三元运算符部分

a. 内置管道

  • 内置管道包括

    管道 功能
    date 格式化日期
    json 经过 JSON.stringify()
    uppercase 字母大写转换
    lowercase 字母小写转换
    decimal 数值特定格式
    currectcy 数值货币格式
    percent 数值百分比格式
    slice 切片成新子集
  • 举例:

    • app.component.ts

      // ...
      import { CommonModule } from '@angular/common';
      
      @Component({
        // ...
        imports: [/* ... */, CommonModule],
      })
      export class AppComponent {
        today: Date = new Date();
      } 
      
    • app.component.html

      <p>{{ today | date: 'yyyy-MM-dd HH:mm:ss'}}</p>
      

b. 自定义管道

使用命令 ng g p newPipe 生成名为 newPipe 的自定义管道,通过 @Pipe 装饰器标识管道

  • prefix.pipe.ts

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({
      name: 'prefix',
      standalone: true,
    })
    export class PrefixPipe implements PipeTransform {
      transform(value: string, ...args: unknown[]): unknown {
        return `angular-${value}`;
      }
    }
    
  • app.component.ts

    // ...
    import { CommonModule } from '@angular/common';
    import { PrefixPipe } from './prefix.pipe';
    
    @Component({
      // ...
      imports: [/* ... */, CommonModule, PrefixPipe],
    })
    export class AppComponent {}
    
  • app.component.html

    <p>{{ "SRIGT" | prefix }}</p>
    

0x04 依赖注入

(1)服务

  • 从组件中抽离出来的代码成为服务,其本质上是函数

    • 主要将数据访问的职责从组件中独立成服务,使组件专注于数据展示
  • 使用命令 ng g s list 生成一个名为 list 的服务,通过 @Injectable 装饰器标识服务

    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root',
    })
    export class ListService {
      constructor() {}
    }
    
  • 服务需要作为依赖,注入到系统、组件或模块才能使用,通过注册提供商和根注入器实现

(2)依赖注入

  • 在上述新建的服务中,providedIn: 'root' 指定 Angular 应该在根注入器中提供该服务

  • providedIn 取值包括:

    • 'root':注入到 App Module,所有子组件都可以使用
    • null:不设定服务在作用域
    • 组件名:只作用于该组件,常用于懒加载
  • 完善上述服务:

    • list.service.ts

      import { Injectable } from '@angular/core';
      
      @Injectable({
        providedIn: 'root',
      })
      export class ListService {
        constructor() {}
      
        names = ['Alex', 'Bob', 'Charlie'];
      
        getNames() {
          return this.names;
        }
      }
      
    • app.component.ts

      // ...
      import { ListService } from './list.service';
      
      @Component({/* ... */})
      export class AppComponent {
        constructor(private listService: ListService) {}
      
        names: Array<string> | undefined;
      
        ngOnInit() {
          this.names = this.listService.getNames();
        }
      }
      
    • app.component.html

      <ul>
        @for (name of names; track $index) {
        <li>{{ name }}</li>
        }
      </ul>
      

0x05 路由

(1)配置

  • 路由器(Router)是一套规则列表,可用于查询 URL 对应的视图规则

  • 路由(Route)是列表中的一条规则

    • path:URL 目标
    • component:对应视图(组件)
  • 一般地,路由规则配置在 .routes.ts 文件中,如 app.routes.ts:

    import { Routes } from '@angular/router';
    
    export const routes: Routes = [];
    
  • 举例,设置链接,从 / 跳转至 /hello

    1. app.routes.ts

      import { Routes } from '@angular/router';
      import { HelloComponent } from './hello/hello.component';
      
      export const routes: Routes = [
        {
          path: 'hello',
          component: HelloComponent,
        },
      ];
      
    2. app.component.ts

      import { Component } from '@angular/core';
      import { RouterLink, RouterOutlet } from '@angular/router';
      
      @Component({
        selector: 'app-root',
        standalone: true,
        imports: [RouterOutlet, RouterLink],
        templateUrl: './app.component.html',
        styleUrl: './app.component.css',
      })
      export class AppComponent {}
      
    3. app.component.html

      <a [routerLink]="['/hello']">Hello</a>
      <router-outlet></router-outlet>
      
    4. hello.component.html

      <p>Hello, Angular</p>
      
  • 使用通配路由实现 404 页面

    export const routes: Routes = [
      // ...
      {
        path: '**',
        component: NotFoundComponent,
      },
    ];
    

(2)嵌套

  • 路由规则的 children 属性可用于实现路由嵌套

    // filename: app.routes.ts
    import { Routes } from '@angular/router';
    import { HelloComponent } from './hello/hello.component';
    
    export const routes: Routes = [
      {
        path: 'hello',
        component: HelloComponent,
        children: [
          {
            path: 'angular',
            component: HelloComponent,
          },
        ],
      },
    ];
    
  • 在非父级路由 /hello 需要跳转到 /hello/angular 时,需要些完整路径

    <!-- filename: app.component.html -->
    <a [routerLink]="['/hello/angular']">Hello</a>
    <router-outlet></router-outlet>
    

(3)传参

  • query:通过 <a>queryParams 参数传递参数,通过 ActivatedRoute.snapshot.queryParams 获取参数

    1. app.component.html

      <a [routerLink]="['/hello']" [queryParams]="{ name: 'Angular' }">Hello</a>
      <router-outlet></router-outlet>
      
    2. hello.component.ts

      import { Component } from '@angular/core';
      import { ActivatedRoute } from '@angular/router';
      
      @Component({/* ... */})
      export class HelloComponent {
        constructor(private activatedRoute: ActivatedRoute) {}
      
        name = ""
      
        ngOnInit() {
          this.name = this.activatedRoute.snapshot.queryParams["name"]
        }
      }
      
    3. hello.component.html

      <p>Hello, {{ name }}</p>
      
  • params:通过在路由配置中加入参数名来传递参数,通过 `` 获取参数

    1. app.routes.ts

      import { Routes } from '@angular/router';
      import { HelloComponent } from './hello/hello.component';
      
      export const routes: Routes = [
        {
          path: 'hello/:name',
          component: HelloComponent,
        },
      ];
      
    2. hello.component.ts

      import { Component } from '@angular/core';
      import { ActivatedRoute, Params } from '@angular/router';
      
      @Component({
        selector: 'app-hello',
        standalone: true,
        imports: [],
        templateUrl: './hello.component.html',
        styleUrl: './hello.component.css',
      })
      export class HelloComponent {
        constructor(private activatedRoute: ActivatedRoute) {}
      
        name = '';
      
        ngOnInit() {
          this.activatedRoute.params.subscribe(
            (params: Params) => (this.name = params['name'])
          );
        }
      }
      
    3. hello.component.html

      <p>Hello, {{ name }}</p>
      
    4. 访问 http://localhost:4200/hello/angular

更多详细内容参考官方文档

-End-

标签:...,18,app,hello,component,ts,angular,开发,Angular
From: https://www.cnblogs.com/SRIGT/p/18520352

相关文章

  • 国标GB28181设备管理软件LiteGBS国标GB28181-2016平台构建雪亮工程视频监控系统
    近年来,“雪亮工程”在全国范围内得到了大力推广和实施。该工程秉承“群众的眼睛是雪亮的”这一核心理念,利用现代信息技术,旨在提高基层治安综合治理的能力,特别是在治安防控、人口服务、信息宣传和矛盾纠纷调解等方面。通过建立三级综治中心,将视频监控系统与综治信息化平台相融合,国......
  • RK3568开发板Openwrt文件系统构建
    iTOP-RK3568开发板使用教程更新,后续资料会不断更新,不断完善,帮助用户快速入门,大大提升研发速度。本次更新内容为《iTOP-3568开发板文件系统构建手册》,对Openwrt文件系统的编译烧写以及系统移植步骤进行详细介绍。      教程目录第1章Linux文件系统简介1.1知识导......
  • rootless容器开发指北
    前言:ruri前不久通过使用uidmap二进制的方式修好了rootless容器无法setgroups()的问题,差不多也该讲讲rootless容器的创建了。rootless容器创建流程:1.设置uidmap我们可以通过读取/etc/subuid和/etc/subgid来获取uid_lower,uid_count和gid_lower,gid_count,他们的格式为:foo:lowe......
  • 软件开发中,做产品与做项目有什么区别
    产品开发和项目开发的区别主要体现在:1.目标不同;2.开发过程不同;3.涉及人员不同;4.时间周期不同;5.结果测评不同。总的来说,产品开发更多侧重于满足市场需求和用户体验,长期维护并进行持续优化;而项目开发更注重完成特定的任务,达到预定的目标。1.目标不同产品开发的目标是创建出能满......
  • 针对充气泵进行方案开发设计过程
    充气泵是一种常见的气体压缩设备,它可以将空气或其他气体压缩成高压气体,用于充气、输送、压缩等工业和生活领域。充气泵的原理是利用机械或电动力量将气体压缩,使其体积减小,压力增大,从而达到充气的目的。充气泵的工作原理可以分为两种类型:机械式和电动式。机械式充气泵是......
  • 开发 react 技术栈的前台项目,选用 semantic-ui-react 组件库是否是较好的选择
    在前端开发中,合适的UI组件库的选择至关重要,它能在保证交互和视觉一致性的同时,大大提升开发效率。Semantic-UI-React是React技术栈中备受关注的UI组件库之一,以其丰富的组件和友好的API受到了许多开发者的欢迎。然而,是否选择它作为项目的UI组件库需结合多个因素综合考虑......
  • 国标GB28181公网平台LiteGBS国标GB28181视频平台建筑工地无线视频联网监控系统方案
    技术的快速进步已经使得视频信号在经过数字化压缩之后,能够通过互联网宽带或移动4G网络进行远程视频监控。将这种尖端技术应用于建筑工地的安全管理,无疑极大地提高了管理的效率,使得监管工作变得更加高效和精确。国标GB28181公网平台LiteGBS监控系统在这一领域中表现卓越,它不仅为建......
  • 如何通过低代码实现高效的小程序开发?
    随着互联网技术的快速发展,越来越多的企业和开发者开始关注并投入到小程序的开发中。然而,小程序开发过程中常常面临复杂的需求和有限的技术资源之间的矛盾。这种情况下,低代码开发方式逐渐成为解决这一问题的重要途径。低代码平台不仅能够提高开发效率,还能减少人力成本,并确保......
  • 安卓APP开发中,如何使用加密芯片?
    加密芯片是一种专门设计用于保护信息安全的硬件设备,它通过内置的加密算法对数据进行加密和解密,以防止敏感数据被窃取或篡改。如下图HD-RK3568-IOT工控板,搭载ATSHA204A加密芯片,常用于有安全防护要求的工商业场景,下文将为大家介绍安卓APP开发中,如何使用此类加密芯片。1. Android......
  • 驱动开发目标测试机器设置
    设置系统为测试模式关闭驱动程序强制签名设置调试消息筛选器掩码一、系统要求需要管理员权限,开启部分功能需要管理员权限不能使用教育版或者家庭版操作系统,可以使用专业版、企业版、旗舰版什么的。部分功能在家庭版中无法开启。二、开启测试模式直接执行命令:bcdedit/......