Angular 2 Pipe

Angular 2 Pipe

Angular 2 中 Pipe(管道) 与 Angular 1.x 中的 filter(过滤器) 的作用的是一样的。它们都是用来对输入的数据进行处理,如大小写转换、数值和日期格式化等。

Angular 2 内建管道

AsyncPipeCurrencyPipeDatePipeDecimalPipeI18nPluralPipeI18nSelectPipe

JsonPipeLowerCasePipePercentPipeSlicePipeTitleCasePipeUpperCasePipe

Angular 2 内建管道使用示例

1.大写转换

<div>  
    <p ngNonBindable>{{ ‘Angular‘ | uppercase }}</p>  
    <p>{{ ‘Angular‘ | uppercase }}</p> 
    <!-- Output: ANGULAR -->
</div>

2.小写转换

<div>  
    <p ngNonBindable>{{ ‘Angular‘ | lowercase }}</p>  
    <p>{{ ‘Angular‘ | lowercase }}</p> 
    <!-- Output: angular -->
</div>

3.数值格式化

<div>  
    <p ngNonBindable>{{ 3.14159265 | number: ‘1.4-4‘ }}</p> 
    <p>{{ 3.14159265 | number: ‘1.4-4‘ }}</p> 
    <!-- Output: 3.1416 -->
</div>

4.日期格式化

<div>  
    <p ngNonBindable>{{ today | date: ‘shortTime‘ }}</p>  
    <p>{{ today | date: ‘shortTime‘ }}</p> 
    <!-- Output: 10:40 AM -->
</div>

5.JavaScript 对象序列化

<div>  
    <p ngNonBindable>{{ { name: ‘semlinker‘ } | json }}</p>  
    <p>{{ { name: ‘semlinker‘ } | json }}</p> 
    <!-- Output: { "name": "semlinker" } -->
</div>

管道参数

管道可以接收任意数量的参数,使用方式是在管道名称后面添加 : 和参数值。如 number: ‘1.4-4‘ ,若需要传递多个参数则参数之间用冒号隔开,具体示例如下:

<div>  
    <p ngNonBindable>{{ ‘semlinker‘ | slice:0:3 }}</p>  
    <p>{{ ‘semlinker‘ | slice:0:3 }}</p> 
    <!-- Output: sem -->
</div>

管道链

我们可以将多个管道连接在一起,组成管道链对数据进行处理。

<div>  
    <p ngNonBindable>{{ ‘semlinker‘ | slice:0:3 | uppercase }}</p>  
    <p>{{ ‘semlinker‘ | slice:0:3 | uppercase }}</p> 
    <!-- Output: SEM -->
</div>

完整示例

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

@Component({ 
    selector: ‘my-app‘,
    template: ` 
        <div>
            <p ngNonBindable>{{ ‘Angular‘ | uppercase }}</p>
            <p>{{ ‘Angular‘ | uppercase }}</p>
        </div>    
        <div>
            <p ngNonBindable>{{ ‘Angular‘ | lowercase }}</p>
            <p>{{ ‘Angular‘ | lowercase }}</p>
        </div>    
        <div>
            <p ngNonBindable>{{ 3.14159265 | number: ‘1.4-4‘ }}</p>
            <p>{{ 3.14159265 | number: ‘1.4-4‘ }}</p>
        </div>
        <div>
            <p ngNonBindable>{{ today | date: ‘shortTime‘ }}</p>
            <p>{{ today | date: ‘shortTime‘ }}</p>
        </div>    
        <div>
            <p ngNonBindable>{{ { name: ‘semlinker‘ } | json }}</p>
            <p>{{ { name: ‘semlinker‘ } | json }}</p>
        </div>
        <div>
            <p ngNonBindable>{{ ‘semlinker‘ | slice:0:3 }}</p>
            <p>{{ ‘semlinker‘ | slice:0:3 }}</p>
        </div>    
        <div>
            <p ngNonBindable>{{ ‘semlinker‘ | slice:0:3 | uppercase }}</p>
            <p>{{ ‘semlinker‘ | slice:0:3 | uppercase }}</p>    
       </div>  `,})
export class AppComponent {  
      today = new Date();
}

自定义管道

自定义管道的步骤:

  • 使用 @Pipe 装饰器定义 Pipe 的 metadata 信息,如 Pipe 的名称 - 即 name 属性
  • 实现 PipeTransform 接口中定义的 transform 方法

1.1 WelcomePipe 定义

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

@Pipe({ name: ‘welcome‘ })export class WelcomePipe implements PipeTransform { 

    transform(value: string): string {    
        if(!value) return value;    
        if(typeof value !== ‘string‘) { 
             throw new Error(‘Invalid pipe argument for WelcomePipe‘);  
        }    
         return "Welcome to " + value;  
     }
}

1.2 WelcomePipe 使用

<div> 
    <p ngNonBindable>{{ ‘semlinker‘ | welcome }}</p>   
    <p>{{ ‘semlinker‘ | welcome }}</p> 
    <!-- Output: Welcome to semlinker -->
</div>

当 WelcomePipe 的输入参数,即 value 值为非字符串时,如使用 123,则控制台将会抛出以下异常:

EXCEPTION: Error in ./AppComponent class AppComponent - inline template:23:9 
caused by: Invalid pipe argument for WelcomePipe

2.1 RepeatPipe 定义

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

@Pipe({name: ‘repeat‘})
export class RepeatPipe implements PipeTransform { 

   transform(value: any, times: number) { 
        return value.repeat(times);    
   }
}

2.2 RepeatPipe 使用

<div>
    <p ngNonBindable>{{ ‘lo‘ | repeat:3 }}</p>
    <p>{{ ‘lo‘ | repeat:3 }}</p>
    <!-- Output: lololo -->
</div>

管道分类

  • pure 管道:仅当管道输入值变化的时候,才执行转换操作,默认的类型是 pure 类型。(备注:输入值变化是指原始数据类型如:string、number、boolean 等的数值或对象的引用值发生变化)
  • impure 管道:在每次变化检测期间都会执行,如鼠标点击或移动都会执行 impure 管道

管道探秘

1.Pipe 相关接口与 PipeDecorator

Pipe 接口定义

export interface Pipe {  name: string;  pure?: boolean;}

PipeDecorator

export const Pipe: PipeDecorator = <PipeDecorator>makeDecorator(‘Pipe‘, {  
    name: undefined, 
    pure: true, // 默认是pure
});

PipeTransform 接口定义

export interface PipeTransform { transform(value: any, ...args: any[]): any;}

2.RepeatPipe 详解

2.1 RepeatPipe 定义

@Pipe({name: ‘repeat‘})
export class RepeatPipe implements PipeTransform { 

    transform(value: any, times: number) { 
        return value.repeat(times);    
    }
}

2.2 RepeatPipe 转换为 ES 5 代码片段

__decorate = (this && this.__decorate) || function (decorators, target, key, 
    desc) {...};     
    
var core_1 = require(‘@angular/core‘);
var RepeatPipe = (function () {

    function RepeatPipe() { }
    
    RepeatPipe.prototype.transform = function (value, times) {
        if (!value) return;
        return value.repeat(times);
    };

    
    RepeatPipe = __decorate([
        core_1.Pipe({ name: ‘repeat‘ }), // 调用PipeDecorator返回TypeDecorator函数
        __metadata(‘design:paramtypes‘, [])
    ], RepeatPipe);
    return RepeatPipe;
}());                                                                                             var core_1 = require(‘@angular/core‘);var RepeatPipe = (function () {    function RepeatPipe() { }    RepeatPipe.prototype.transform = function (value, times) {        if (!value) return;        return value.repeat(times);    };    RepeatPipe = __decorate([        core_1.Pipe({ name: ‘repeat‘ }), // 调用PipeDecorator返回TypeDecorator函数        __metadata(‘design:paramtypes‘, [])    ], RepeatPipe);    return RepeatPipe;}());

2.3 通过 Reflect API 保存后的对象信息

2.4  管道解析 - PipeResolver 源码片段

// @angular/compiler/src/pipe_resolver.ts
@CompilerInjectable()
export class PipeResolver {  
    constructor(private _reflector: ReflectorReader = reflector) { }  
    
    // 通过内部的ReflectorReader对象提供的API读取metadata信息  
    resolve(type: Type<any>, throwIfNotFound = true): Pipe {   
         const metas = this._reflector.annotations(resolveForwardRef(type));   
      if (metas) {      // 读取保存的Pipe metadata 信息      
          const annotation = ListWrapper.findLast(metas, _isPipeMetadata);   
          if (annotation) { 
              return annotation; 
          }    
      }  
          if (throwIfNotFound) {      
              throw new Error(`No Pipe decorator found on ${stringify(type)}`);   
           }    
           return null; 
  }
}

2.5 RepeatPipe 管道的创建与执行

2.5.1 管道的创建

// JS has NaN !== NaN
function looseIdentical(a, b): boolean { 
  return a === b || typeof a === ‘number‘ && typeof b === ‘number‘ 
     && isNaN(a) && isNaN(b);
}
     
// 用于检测管道的输入值或参数值是否变化,若发生变化则自动调用管道transform转换函数
function jit_pureProxy214(fn) { 
    var result; 
    var v0 = UNINITIALIZED; // { toString: function() { return ‘CD_INIT_VALUE‘} };      
    var v1 = UNINITIALIZED;        
    
   return function (p0, p1) {            
      if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1)) {
      v0 = p0; // p0: "lo"               
      v1 = p1; // p1: 3    
      // fn: transform(value: any, times: number) { return value.repeat(times); }                       
        result = fn(p0, p1); // 调用管道的transform转换函数            
        }           
      return result;        
   };
}

self._pipe_repeat_6 = new jit_RepeatPipe18(); // 创建RepeatPipe对象
self._pipe_repeat_6_0  = jit_pureProxy214( // 代理RepeatPipe中transform函数  
self._pipe_repeat_6.transform.bind(self._pipe_repeat_6));

2.5.2 管道的执行

在 Angular 执行变化检测时,会自动调用管道中的 transform 方法

var currVal_100 = jit_inlineInterpolate21(1,‘‘,
    valUnwrapper.unwrap( jit_castByValue22 (self._pipe_repeat_6_0,  
     self._pipe_repeat_6.transform)(‘lo‘,3))
,‘‘);

总结

本文介绍了 Angular 2 中的常用内建管道的用法和管道的分类,同时也介绍了 pure 和 impure 管道的区别。 此外我们通过两个示例展示了如何自定义管道,最后详细分析了 RepeatPipe 管道的工作原理。建议读者更改 RepeatePipe 的 pure 属性为 false,体验一下 impure 管道。

时间: 2024-10-11 05:16:51

Angular 2 Pipe的相关文章

[Angular 2] Pipe Purity

Explaining how Pipes only change by default when your Pipe input parameters change and not when your data changes. It also shows you how to make an “unpure” pipe if you always want your pipe to update. import {Pipe} from 'angular2/angular2'; @Pipe({

[Angular 2] Understanding Pure &amp; Impure pipe

First, how to use a build in pipe: <div class="pipe-example"> <label>Uppercase Pipe: {{ message | uppercase }}</label> </div> <div class="pipe-example"> <label>Lowercase Pipe: {{ message | lowercase

[Angular Unit Testing] Testing Pipe

import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'filesize' }) export class FileSizePipe implements PipeTransform { transform(size: number, extension: string = 'MB') { return (size / (1024 * 1024)).toFixed(2) + extension; } } import

angular之自定义管道

1,装了angular2 的 cli之后,cmd中命令建立个管道文件 ng g p <name>; 如建一个在pipe文件中建一个add.pipe.ts文件 可以这么么写 ng g p pipe/add; 2,  add.pipe.ts内容如下: //原始内容import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'add' }) export class AddPipe implements PipeTransfo

angular2 pipe实现搜索结果中的搜索关键字高亮

效果图如下 1.声明一个pipe import {Pipe, Injectable, PipeTransform} from '@angular/core';import { DomSanitizer } from '@angular/platform-browser'@Pipe({ name: 'keyword'})@Injectable()export class KeywordPipe implements PipeTransform { constructor(private sanit

angular自定义管道

对自定义管道的认识 管道的定义中体现了几个关键点: 1.管道是一个带有"管道元数据(pipe metadata)"装饰器的类. 2.这个管道类实现了PipeTransform接口的transform方法,该方法接受一个输入值和一些可选参数,并返回转换后的值. 3.当每个输入值被传给transform方法时,还会带上另一个参数,比如我们这个管道中的exponent(放大指数). 4.我们通过@Pipe装饰器告诉Angular:这是一个管道.该装饰器是从Angular的core库中引入的.

FastReport教程:如何在单页应用程序Angular 7中使用Web报表

下载FastReport.Net最新版本 如果您在ASP.Net Core应用程序中使用FastReport.Net并希望切换到单页应用程序(SPA),那么本文适合您. 由于Angular和ASP.Net Core的共生,您可以使用您熟悉的MVC应用程序架构. 我们来看看创建SPA应用程序的方法.这对那些刚刚学习Angular的人很有用.要使用Angular,您需要安装Node.js,这是一个在服务器端执行JavaScript代码的平台. 最简单的方法是从开发人员的网站https://nodej

angular 中嵌套 iframe 报错

错误如下 Error: unsafe value used in a resource URL context at DomSanitizationServiceImpl.sanitize... 解决 import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer} from '@angular/platform-browser'; @Pipe({ name: 'safe' }) export class Sa

Angular中innerHTML标签的样式不起作用详解

1.背景 在最近angular的项目中,需要用到[innerHTML]标签来指定一个div的样式: 1 //HTML部分 2 <div class="contents" [innerHTML]="contents"></div> 3 4 //TS部分 5 contents = '<p>商品信息栏位<br><span style="color:red;">商品信息介绍</span&g