Angular2管道的笔记

结论。

现在不可能

我完全理解了 (有点小自豪感)

管子,比我想象的厉害多了。多亏了@shuhei的评论,我能够大步向前了。

准备准备

创建Pipe

在中文中,我们可以这样翻译上述内容:

Pipe类是继承自Pipe类的一个类。继承自Pipe类的类必须具备supports和transform这两个方法。另外,我们还需要创建一个用于实例化Pipe对象的PipeFactory。PipeFactory类必须具备create方法。这两者并不一定需要是不同的类,Pipe类本身也可以充当PipeFactory的角色。

接收一个字符串,定义如下的Pipe和其Factory,使其重复两次。

import 'package:angular2/change_detection.dart';

class DoublePipeFactory extends Pipe {
  bool supports(obj) {
    return obj is String;
  }

  dynamic transform(dynamic value) {
    return "${value}${value}";
  }

  Pipe create(ChangeDetectorRef cdRef) {
    return this;
  }
}

从Pipe类中进行覆盖的是以下两个方法。

是否支持(obj)

给定一个动态类型(JS中为any?)的对象,并判断管道是否有效。给定的对象是在使用管道时的左侧。由于本次仅限制为字符串类型,所以当为String类型时返回true。

动态转换(动态值)

进行Pipe的转换操作。返回类型不需要与参数匹配,例如可以创建一个接收列表并返回仅包含第一个元素的Pipe。

我们已经实现了以下方法来作为PipeFactory的行为。

创建一个管道(ChangeDetectorRef cdRef)。

返回Pipe的实例。由于此次Pipe本身兼具工厂功能,因此返回this。参数cdRef用于控制更新时机,但在同步处理范围内不需要使用。具体的使用方法可以参考内置的AsyncPipe实现。

将信息注册到PipeRegistry

创建的Pipe可以通过将其注册到PipeRegistry中,使其能够在Angular中作为Pipe使用。由于还没有简洁的API来进行注册,所以目前的实现相对较为笨拙。是否有改进的空间呢?

将Pipe添加到defaultPipeRegistry。

从已注册的defaultPipeRegistry中提取config,这是一个内部映射,其中包含keyValDiff、iterableDiff、async等内置的Pipe。然后创建一个新的配置,其中嵌入自定义的Pipe。需要注意的是,传递给映射的不是Pipe也不是PipeFactory,而是PipeFactory的列表。这是为了按优先顺序提取具有相同名称的PipeFactory列表中的第一个Pipe实例,并调用supports方法使用它。

import 'package:angular2/change_detection.dart';
import 'double/double.dart';
import 'filter/filter.dart';

dynamic get pipes {
  var config = defaultPipeRegistry.config;
  config["double"] = [new DoublePipeFactory()];
  return config;
}

注册应用程序

在Angular2启动时,将创建的配置注册到绑定中。

import "package:angular2/src/reflection/reflection.dart";
import "package:angular2/src/reflection/reflection_capabilities.dart";
import 'package:helloworld/component/app_component.dart';
import 'package:angular2/di.dart';
import 'package:helloworld/pipe/pipes.dart';

main() {
  reflector.reflectionCapabilities = new ReflectionCapabilities(); //dart版では暫定的に必要らしいコードなので無視

  var injectables = [bind(PipeRegistry).toValue(new PipeRegistry(pipes))];

  bootstrap(AppComponent, injectables);
}

只要完成注册,之后就只需要使用了。

在{{}}之中使用

我们将创建一个名为double-value的组件,它是一种非常简单的形式。它会将文本属性的字符串重复两次显示。

import "package:angular2/angular2.dart";
import 'package:helloworld/component/double/double_component.dart';

@Component(selector: 'my-app')
@View(
    templateUrl: 'component/app.html',
    directives: const [DoubleComponent])
class AppComponent {
  var text = "ABC";

  AppComponent() {}
}
<double-value [text]="text"></double-value>
import "package:angular2/angular2.dart";

@Component(selector: "double-value", properties: const {"text": "text"})
@View(templateUrl: "component/double.html")
class DoubleComponent {
  String text;
}
<h2>Double Pipe</h2>
<span>{{ text | double }}</span>
スクリーンショット 2015-05-04 21.43.22.png

我们制作了一个专门用于便宜的组件,但当然也可以在根HTML中使用。

在属性的值中使用

这是一个在使用for循环时的情境。在将值传递给Directive之前,会先应用Pipe。如果将前一个app.html修改如下,当将值传递给Directive时,Pipe将会作用两次,分别在内部和外部。

<double-value [text]="text | double"></double-value>
スクリーンショット 2015-05-04 21.46.49.png

在Directive定義中使用

由于这个用法,非常混乱。这是一种在脚本中而不是HTML中应用Pipe的语法。在@Component的properties中使用。

当传递给Directive的值被绑定到内部属性时,Pipe会被应用。因此,通过修改double_component.dart如下,可以再次通过Pipe传递一次,总共发生3次重复。

import "package:angular2/angular2.dart";

@Component(selector: "double-value", properties: const {"text": "text | double"})
@View(templateUrl: "component/double.html")
class DoubleComponent {
  String text;
  DoubleComponent() : super() {}
}
スクリーンショット 2015-05-04 21.49.54.png

通过将属性绑定到setter函数,可以看到管道在绑定后仍在起作用,就像下面的例子一样。

import "package:angular2/angular2.dart";

@Component(
    selector: "double-value", properties: const {"textChange": "text | double"})
@View(templateUrl: "component/double.html")
class DoubleComponent {
  String text;

  set textChange(String newText) {
    this.text = newText + "_";
  }

  DoubleComponent() : super() {}
}
スクリーンショット 2015-05-04 21.56.22.png

当收到不支持的对象时的行为

如果将数字100传递给双管道(double Pipe),那么将从PipeRegistry的double中注册的PipeFactory中查找supports(100) == true的Pipe,如果找不到,则会出现错误提示。

Cannot find 'double' pipe supporting object '100' in [text| double in AppComponent]

总结

现在说什么都太勉强了,对不起!
虽然还有点早,但已经到了可以使用的水平。
由于是Dart版,细节可能与JS不同,请尽量克服这些困难。在Angular2的世界中,Dart和JS的区别不过是微不足道的事情。

希望未来能改善的方面是

    • PipeRegistry周りもうちょっとAPI整備して綺麗に書けるようにしてくれ

 

    なぜPipeFactoryはクラスがないのか…(createメソッドがないとダメだっていうエラーは出すくせに)

只是大约这样。

以上的内容。

bannerAds