两种跨页面传值的方式:URL和localStorage

537 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

适用场景一

在表格中进入指定订单的详情页面时,有两个个标识符为planId(计划ID)和orderId(订单ID)
此时URL设置为“组件路径/planId/orderId”的形式,两个ID需要在调用API时传值。

先设置按钮的跳转:

 <button mat-stroked-button 
 [routerLink]="'/apps/planmanage/purchase-order-list/audit/' + row.plan_id + '/' + row.order_id">
 编辑/审核</button>
//'/apps/planmanage/purchase-order-list/audit/'为详情页的组件路径
//'row.plan_id'中的row为表格循环遍历的字段,plan_id和order_id则是取对应的计划编号和订单编号

在权限、路由中设置详情组件的URL:

const routes: Routes = [
  {
    path: 'purchase-order-list/audit/:plan_id/:order_id',
    component: PurchaseOrderAuditComponent,
  }
];

注:其中path中的plan_id和order_id为用于获取值的标识符,如果两个都写为ID会无法正确获取。

在详情页中声明:

import { ActivatedRoute } from '@angular/router';
constructor(
    private route: ActivatedRoute,
  )

在ngOnInit周期中获取ID:

ngOnInit(): void {
    // 获取plan_id
    this.planId = this.route.snapshot.params.plan_id;
    // 获取order_id
    this.orderId = this.route.snapshot.params.order_id;
  }

调用API:

const url = `planOrder/detail?plan_id=${this.planId}&order_id=${this.orderId}`;
this.confSvc.sendGetCatch(url, this.isLoading).subscribe(res => {
    // 获取订单详细信息
    const arrayDataBasic: any[] = res['data'].basic || [];
    this.orderData = arrayDataBasic[0];
});

适用场景二

当需要跨页面传的值数量过多时,使用URL+值的方式不仅容易超出浏览器规定的长度,而且也不合理。
下面场景中,需要通过搜索栏的多个元素,点击打印按钮后跳转到打印界面,再根据搜索栏选中的元素进行API调用并渲染。
于是有一种方法是使用localStorage缓存的方式进行传值。

当点击打印按钮时,对搜索栏的值进行保存:

savePrintCondition(): void {
    const searchCondition = {
      orderId: this.orderId.value,
      spu: this.spu.value,
      orderStatus: this.orderStatus.value,
      isNew: this.isNew.value,
      dateType: this.dateType.value,
      brand: this.brand.value,
      buyer: this.buyer.value,
      gendan: this.gendan.value,
      sProductCat2: this.sProductCat2.value,
      dateBeyond: this.dateBeyond.value,
      supplier: this.supplier.value,
      orderType: this.orderType.value,
      productionState: this.productionState.value,
      fromDate: this.fromDate.value !== null ? this.general.formatTimeToDate(this.fromDate.value) : null,
      toDate: this.toDate.value !== null ? this.general.formatTimeToDate(this.toDate.value) : null,
      DevelopStatus: this.DevelopStatus.value,
      isAmazon: this.isAmazon.value
    };

    // purchaseOrdersPrint为缓存的名称,方便后续调用
    localStorage.setItem('purchaseOrdersPrint', JSON.stringify(searchCondition));
  }

进入打印页面后,在打印页面对应的组件的ngOnInit周期中读取缓存:

ngOnInit(): void {
    const oldSearchCondition = JSON.parse(localStorage.getItem('purchaseOrdersPrint'));

    this.orderId.setValue(oldSearchCondition.orderId);
    this.spu.setValue(oldSearchCondition.spu);
    this.orderStatus.setValue(oldSearchCondition.orderStatus);
    this.isNew.setValue(oldSearchCondition.isNew);
    this.dateType.setValue(oldSearchCondition.dateType);
    this.brand.setValue(oldSearchCondition.brand);
    this.buyer.setValue(oldSearchCondition.buyer);
    this.gendan.setValue(oldSearchCondition.gendan);
    this.sProductCat2.setValue(oldSearchCondition.sProductCat2);
    this.dateBeyond.setValue(oldSearchCondition.dateBeyond);
    this.supplier.setValue(oldSearchCondition.supplier);
    this.orderType.setValue(oldSearchCondition.orderType);
    this.productionState.setValue(oldSearchCondition.productionState);
    this.fromDate.setValue(oldSearchCondition.fromDate);
    this.toDate.setValue(oldSearchCondition.toDate);
    this.Type = this.orderType.value;
  }

注意,在打印界面的组件中,orderId等需要使用的字段需要提前设置例如:

orderId = new FormControl(null);

这样在ngOnInit周期中读取缓存,直接调用的字段就是已经传值完成的字段。

总结

跨页面传值时,遇到需要传值的元素较少时可以采用URL传值,并且URL后的ID也可以作为系统/页面的标识符。
但需要传值的元素过多,浏览器的URL长度有所限制,观感上也会导致很杂乱,采用localStorage传值为佳。

读取传值的语句在不同位置会有不同的效果,优先级尽量放在前列,如果放在ngAfterViewInit中,页面先进行API调用再读取,则无法成功调用和渲染。