Angular(三):进阶

本文详细介绍了Angular中路由配置及使用方法,包括GET传值、动态路由等,并深入探讨了依赖注入的实现原理及自定义管道的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

路由

在这里插入图片描述

子路由

在这里插入图片描述

路径参数

在这里插入图片描述

路径对象参数

在这里插入图片描述

查询参数

在这里插入图片描述


页面传值

GET传值:

<!-- 常规 -->
<a href="/info?id=123">详情123</a>

<!-- Angular GET传值
-->
<a [routerLink]="['/info']" [queryParams]="{id:key}">详情{{key}}</a>

获取get传值的id值:

this.route.queryParams.subscribe((date)=>{
	console.log(date);
})

动态路由:

<a [routerLink]="['info', key]">详情{{key}}</a>

获取动态路由的值:

this.route.params.subscribe((data)=>{
    console.log(date);
})

js页面跳转

动态路由的js跳转:

// 1. 构造函数注入@angular/router:Router
// 2. 跳转:
this.router.navigate(['/info', '123'])

get传值的js跳转:

// 1. 构造函数注入@angular/router:Router + @angular/router:NavigationExtras
// 2. 跳转:
let navigationExtras: NavigationExtras = {
	// 传递两个参数的情况
	queryParams: {'seesion_id': 123},
	fragment: 'onefine'
}

this.router.navigate(['main'], navigationExtras);

管道

在这里插入图片描述
内置管道示例:
src\app\app.component.ts:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  
  title = 'ifine';

  obj = {name: 'onefine', age: 18, home: 'km'}

  date: Date;

  price: number;
  
  data = [1, 2, 3, 4, 5, 6, 7];

  constructor() {
    this.date = new Date();
    this.price = 123456.123;
  }
}

src\app\app.component.html:

<p> {{ obj | json }}</p>

<p> {{ date | date: 'MM-dd' }}</p>

<p> {{ price | currency }} </p>

<p> {{ price | currency: 'CNY' }} </p>

<p> {{ data | slice:1:3 }}</p>

在这里插入图片描述

另外,加载中文相关资源[可选]:

src\app\app.module.ts:

import { LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeModule } from './home';
import { SharedModule } from './shared/shared.module';

import localZh from '@angular/common/locales/zh-Hans';
import { registerLocaleData } from '@angular/common';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    SharedModule,
    AppRoutingModule,
    HomeModule
  ],
  providers: [
    {
      provide: LOCALE_ID,
      useValue: 'zh-Hans'
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor() {
    // 注册中文相关数据
    registerLocaleData(localZh, 'zh');
  }
}

在这里插入图片描述
自定义管道示例:

src\app\shared\pipes\ago.pipe.ts:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'appAgo'
})
export class AgoPipe implements PipeTransform {
    transform(value: any, ...args: any[]): any {
        if (value) {
            // 转为时间戳 / 1000
            const seconds = Math.floor((+new Date() - +new Date(value)) / 1000);
            if (seconds < 30) {
                return '刚刚';
            }
            const intervals = {: 3600 * 24 * 365,: 3600 * 24 * 30,: 3600 * 24 * 7,: 3600 * 24,
                小时: 3600,
                分钟: 60,: 1
            };
            
            let counter = 0;
            for (const unitName in intervals) {
                const unitValue = intervals[unitName as keyof typeof intervals];
                counter = Math.floor(seconds / unitValue);
                if (counter > 0) {
                    return `${counter} ${unitName} 前`;
                }
            }

            

            return value;
        }
    }
}

src\app\app.component.ts:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  title = 'ifine';

  date: Date;

  constructor() {
    this.date = this.minusDays(new Date(), 2);
  }

  minusDays(date: Date,  days: number): Date {
    const result = new Date(date);
    result.setDate(result.getDate() - days);
    return result;
  }
}

src\app\app.component.html:

<p> {{ date | appAgo }}</p>

依赖注入

在这里插入图片描述

import { Component, Injectable, Injector, OnInit } from '@angular/core';

// 产品
@Injectable()
class Product {
  constructor(private name: string, private clolr: string) {}

}

// 订单
@Injectable()
class PurchaseOrder {
  private amount: number = 0;
  constructor(private product: Product) { }
}


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

  constructor() { }

  ngOnInit() {
      const injector = Injector.create({
        // 描述创建方式
        providers: [
          {
            provide: Product,
            // useClass: Product
            useFactory: () => {
              return new Product("iPhone", "blue");
            },
            deps: []
          },
          {
            provide: PurchaseOrder,
            useClass: PurchaseOrder,
            deps: [Product]
          }
        ]
      });

      console.log(injector.get(Product));
      console.log(injector.get(PurchaseOrder));

  }

}

或者:

import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SharedModule } from './shared/shared.module';

import localZh from '@angular/common/locales/zh-Hans';
import { registerLocaleData } from '@angular/common';
import { HomeService } from './home/services';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    SharedModule,
    AppRoutingModule,
    HomeModule,
  ],
  providers: [
    // PurchaseOrder,
    // {
    //   provide: Product,
    //   // useClass: Product,
    //   useFactory: () => {
    //     return new Product("one day");
    //   },
    //   // 描述依赖性
    //   deps: []
    // }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Angular提供的方式:

src\app\home\services\home.service.ts:

import { Injectable } from '@angular/core';
import { Channel, ImageSlider, TopMenu } from 'src/app/shared/components';

// @Injectable({ providedIn: 'root' })
@Injectable()
export class HomeService {
    constructor() {

    }

    topMenus: TopMenu[] = [
        {
            title: '热门',
            link: 'hot',
            id: 1
        },
        {
            id: 2,
            title: '男装',
            link: 'men'
        },
        {
            id: 3,
            title: '百货',
            link: 'department'
        }
    ];

    getTopMenus() {
        return this.topMenus;
    }
}

src\app\home\components\home-container\home-container.component.ts:

import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { TopMenu, ImageSliderComponent } from 'src/app/shared/components';
import { HomeService } from '../../services';

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

  constructor(private homeService: HomeService) { }

  ngOnInit() {
    this.topMenus = this.homeService.getTopMenus();
  }

  topMenus: TopMenu[] = [];
}

src\app\home\home.module.ts:

import { NgModule } from '@angular/core';

import { HomeRoutingModule } from './home-routing.module';
import { SharedModule } from '../shared/shared.module';
import { HomeContainerComponent, HomeDetailComponent } from './components';
import { HomeService } from './services';


@NgModule({
  declarations: [HomeContainerComponent, HomeDetailComponent],
  providers: [HomeService],  // <--here
  imports: [
    HomeRoutingModule,
    SharedModule,
  ]
})
export class HomeModule { }

注入值:

src\app\home\components\home-grand\index.ts:

import { InjectionToken } from '@angular/core';

export const token = new InjectionToken<string>('baseUrl');

src\app\home\components\home-grand\home-grand.component.ts:

import { Component, Inject, Injectable, InjectionToken, Injector, OnInit } from '@angular/core';
import { token } from '.';

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

  constructor(@Inject(token) private baseUrl: string) { }

  ngOnInit() {
      const injector = Injector.create({
        // 描述创建方式
        providers: [
	      {
	        // provide: 'baseUrl',
	        provide: this.baseUrl,  // 使用Token
	        useValue: 'http://127.0.0.1'
	      }
        ]
      });

      console.log("baseUrl: " + injector.get('baseUrl'));
  }
}

脏值检测

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
src\app\home\components\child\child.component.ts:

import { formatDate } from '@angular/common';
import { Component, ElementRef, NgZone, OnInit, Renderer2, ViewChild } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
  private _title: string;
  private _time: number;
  public get title(): string {
    console.log("脏值检测");
    return this._title;
  }

  public get time(): number {
    return this._time;
  }

  constructor(private ngZone: NgZone, private rd: Renderer2) {
    this._title = 'hi';
    this._time = Date.now();
  }

  @ViewChild('timeRef', { static: true }) timeRef!: ElementRef;

  ngOnInit() {
  }

  ngAfterViewChecked(): void {
    // this._title = 'nihao';  // 抛出异常
    // angular之外运行
    this.ngZone.runOutsideAngular(() => {
      // 异步
      setInterval(() => {
        this._title = 'nihao';
        this._time =  Date.now();
        // this.timeRef.nativeElement.innerText = Date.now();
        this.rd.setProperty(this.timeRef.nativeElement, 'innerText', 
          // Date.now()
          // 使用管道操作日期格式
          formatDate(Date.now(), 'HH:mm:ss:SSS', 'zh-Hans')
        );
      }, 100);
    });
  }

  handleClick() {}
}

src\app\home\components\child\child.component.html:

<p>
  child works!
</p>

<hr>
<span [textContent]="title"></span>
<hr>
<span [textContent]="time | date: 'HH:mm:ss:SSS'"></span>
<hr>
<button (click)="handleClick()">触发脏值检测</button>
<br>
<span>倒计时-直接操作DOM而不是采用绑定: </span>
<span #timeRef></span>

OnPush策略:

import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ImageSlider } from 'src/app/shared/components';
import { Channel } from 'src/app/shared/components/horizontal-grid';
import { HomeService } from '../../services';

@Component({
  selector: 'app-home-detail',
  templateUrl: './home-detail.component.html',
  styleUrls: ['./home-detail.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush  // OnPush策略
})
export class HomeDetailComponent implements OnInit {

  constructor(private route: ActivatedRoute, 
    private homeService: HomeService,
    private cd: ChangeDetectorRef
    ) { }

  selectedTabLink: string | null | undefined;

  ngOnInit() {
    this.route.paramMap.subscribe(params => {
      this.selectedTabLink = params.get('tabLink');
      this.cd.markForCheck();  // 手动检查
    });

    this.imageSliders = this.homeService.getImageSliders();
    this.channels = this.homeService.getChannels();
  }

  imageSliders: ImageSlider[] = [];

  channels: Channel[] = [];

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值