我正在学习 Angular 18 SSR。当我从 graphql 服务加载数据时,我遇到了渲染问题;使用从服务可观察方法转换的信号加载值来显示负载元素(骨骼);问题是当我渲染时,它同时显示骨架和项目(当加载数据结束时,仅显示项目):
产品.服务.ts
@Injectable({
providedIn: 'root'
})
export class ProductsService {
private apollo = inject(Apollo);
getProductsPaginated(quantity:number, page:number): Observable<ProductResponse>{
return this.apollo.watchQuery({
query: GET_PRODUCTS,
variables: { quantity, page }
}).valueChanges.pipe(
map(({ data, error }: any) => ({
loading: false,
products: data.productsPaginated.nodes,
error: error
}))
);
}
}
:
@Component({
selector: 'app-shop',
standalone: true,
imports: [SidebarMenuComponent, ProductCardComponent, ProductCardSkeletonComponent],
templateUrl: './shop.component.html',
styleUrl: './shop.component.css'
})
export default class ShopComponent{
public skeletonProductsLenght = [1, 2, 3, 4, 5, 6];
public productsService = inject(ProductsService);
public productsPaginatedResp =
toSignal(this.productsService.getProductsPaginated(12,1),
{ initialValue: { loading: true, products: [], error: false } });
}
:
<div class="grid md:grid-cols-3 grid-cols-2 gap-6 p-4">
@if(this.productsPaginatedResp()?.loading){
@for(item of skeletonProductsLenght; track item){
<app-product-card-skeleton/>
}
}
@else {
@for (item of this.productsPaginatedResp()?.products; track item.key) {
<app-product-card [product]="item"/>
}
}
</div>
defer
使代码仅在浏览器上执行。这样,只有 HTML 呈现一次,它要么是骨架,要么是产品。
推迟文档
@defer {
<div class="grid md:grid-cols-3 grid-cols-2 gap-6 p-4">
@if(this.productsPaginatedResp()?.loading){
@for(item of skeletonProductsLenght; track item){
<app-product-card-skeleton/>
}
}
@else {
@for (item of this.productsPaginatedResp()?.products; track item.key) {
<app-product-card [product]="item"/>
}
}
</div>
}