管道

管道:(非官方释义)数据显示在模板上之前需要根据某些条件作出进一步处理,比如格式化等。可以理解为执行自定义的方法,参数为绑定的数据。

内置管道

Angular内置十几种内置管道用于常规开发和调试,如转化为json的管道 json ,使用示例:

{{ obejct | json }}

还有时间格式转换的date,英文词转小写的 lowercase 等。

对管道进行参数化

管道对数据处理时候可能还配置了多种option模式,如果要指定option,得告诉这个管道,这个过程叫做管道参数化,例如 : {{ new Date() | data:'shortDate'}}

链式管道

多层管道处理,jquery链式写法是‘.’;管道则是‘|’,{{new Date()|data|lowercase}}

<div>
  date:{{currentDate}}
  <ul>
    <li>
      使用date管道:{{currentDate|date}}
    </li>
    <li>
      使用参数化的date: {{currentDate|date:'shortDate'}}
    </li>
    <li>
      使用链式管道date、lowercase:{{currentDate|date|lowercase}}
    </li>
  </ul>
</div>

clipboard.png

自定义管道

自定义一个简单的放大倍数的管道指令。
文件名以 ‘.pipe.ts’结尾,expand-data.pipe.ts

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

@Pipe({ name: 'expandData' })
export class ExpandData implements PipeTransform {
  transform(value: number) {
    if (value && isNumber(value)) {
      return 2 * value;
    } else {
      return 0;
    }
  }
}

将管道放在app模块的声明数组种,以便模板能够使用,上述代码是标准的格式代表,一切的执行在这个transform方法种,并且返回最终结果。我声明了一组数组:[1,2,3,4,5],通过ngFor渲染在li列表中。

管道与变更检测

改造下demo和管道:

import { Pipe, PipeTransform } from '@angular/core';
import { isNumber } from 'util';
@Pipe({ name: 'expandData' })
export class ExpandData implements PipeTransform {
  transform(data: Array<any> | any) {
    if (data && isNumber(data)) {
      return 2 * data;
    } else if (typeof (data) !== 'string' && data.length > 0) {
      data = data.filter(o => o.value > 3);
      data.map(o => 2 * o);
      return data;
    }
  }
}
 counts = [
    { id: '0', value: 1 },
    { id: '1', value: 2 },
    { id: '2', value: 3 },
    { id: '3', value: 4 },
    { id: '4', value: 5 }
  ];
  randomChange() {
    this.counts[Math.round(4 * Math.random())].value = Math.round(10 * Math.random());
  }
<div>
  {{counts|json}}
  <ul>
    <li *ngFor="let count of counts | expandData">
      {{count.value}}
    </li>
  </ul>
  <button nz-button (click)="randomChange()">随机改变其中一个数据</button>
</div>

clipboard.png

clipboard.png
尽管真实的数据中符合大于3的已经超过2个,但是页面中还是渲染2个数据。

这里只是用了另一种变更检测算法 —— 它会忽略对列表及其子项所做的任何更改。为了通知Angular更新,需要重新替换数据,解构是个高效的方案。

非纯管道

Angular 会在每个组件的变更检测周期中执行非纯管道。 非纯管道可能会被调用很多次,和每个按键或每次鼠标移动一样频繁。
要在脑子里绷着这根弦,必须小心翼翼的实现非纯管道。 一个昂贵、迟钝的管道将摧毁用户体验。

纯管道

Angular 只有在它检测到输入值发生了纯变更时才会执行纯管道。 纯变更是指对原始类型值(String、Number、Boolean、Symbol)的更改, 或者对对象引用(Date、Array、Function、Object)的更改。
import { Pipe, PipeTransform } from '@angular/core';
import { isNumber } from 'util';
@Pipe({ name: 'expandData',pure:false })
export class ExpandData implements PipeTransform {
  transform(data: Array<any> | any) {
    if (data && isNumber(data)) {
      return 2 * data;
    } else if (typeof (data) !== 'string' && data.length > 0) {
      data = data.filter(o => o.value > 3);
      data.map(o => 2 * o);
      return data;
    }
  }
}

clipboard.png


何弃疗
106 声望7 粉丝

前端路上摸爬滚打;野路子前端debug