我正在使用 Angular 17 并使用新的 Signals API 来管理应用程序中的状态。我有一个服务,它保存浏览器标题的信号,我想在路由解析器中使用该信号。但是,我面临一个问题,解析器仅获取第一个发出的值,该值为 null 默认值,并且不接收后续更新。
服务:
import { Injectable, signal } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
@Injectable({ providedIn: 'root' })
export class CommonService {
public browserTitle = signal<string | null>(null);
public readonly browserTitle$ = toObservable(this.browserTitle);
public setBrowserTitle(title: string | null): void {
this.browserTitle.set(title);
}
}
详细解析器:
import { inject } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { CompanyService } from '../service';
import { CommonService } from '@core/services';
import { ICompanyDetailDataset } from '../models';
import { ResolveFn, Router } from '@angular/router';
import { EMPTY, Observable, catchError, map } from 'rxjs';
export const companyDetailResolver: ResolveFn<Observable<ICompanyDetailDataset>> = (
route,
state
) => {
const companyId = route.params['companyId'];
const _router = inject(Router);
const _toastr = inject(ToastrService);
const _commonService = inject(CommonService);
const _companyService = inject(CompanyService);
return _companyService.fetchCompany(companyId).pipe(
map((companyDetails) => {
_commonService.setBrowserTitle(companyDetails.name);
return { company_details: companyDetails };
}),
catchError((error: Error) => {
_toastr.error(error.message);
_router.navigate(['companies']);
return EMPTY;
})
);
};
标题解析器:
import { Observable, map } from 'rxjs';
import { inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { CommonService } from '@core/services';
export const companyUpdateTitleResolver: ResolveFn<string> = (
route,
state
) => {
const _commonService = inject(CommonService);
return _commonService.browserTitle$.pipe(
map((title) => {
return !title ? 'Update Company' : `Update Company: ${title}`;
})
);
};
Resolver,通常是一个函数,在组件加载之前执行,我们可以在组件加载之前完成一个可观察的,或布尔值,或API调用,但请注意它不会等待新值,它会立即解析,所以你会得到这种行为。
如果你问我
companyUpdateTitleResolver
绝对是多余的,我们可以在第一个解析器本身上获取标题,我们还可以订阅组件加载时信号的变化!
创建一个返回
computed
标题的新属性
import { Injectable, signal, computed } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
@Injectable({ providedIn: 'root' })
export class CommonService {
public browserTitle = signal<string | null>(null);
public readonly browserTitle$ = toObservable(this.browserTitle);
public fullTitle = computed(() => {
const title = this.browserTitle();
return !title ? 'Update Company' : `Update Company: ${title}`;
});
public setBrowserTitle(title: string | null): void {
this.browserTitle.set(title);
}
}
然后在组件加载时我们可以使用数据!
@Component({ ... })
export class SomeComponent {
_commonService = inject(CommonService);
constructor() {
effect(() => {
const newTitle = this._commonService.fullTitle();
// do something with title!
});
}
}