转载

协作翻译 | Angular 2: @Directive() 创建无限滚动

在最近的文章中,我使用  angular 2 中新的 " ng-repeat " 也就是 " NgFor " 结合通用组件创建(自己的)组件。在这篇文章里,我将继续展示,结合 Angular 2进一步开发的  Echoes Player 项目。这次为了更加动态化的展示我们将添加一个无限滚动指令。在Angular 2中无限滚动作为一个属性指令。

Angular 1.x 无限滚动

在当前的 Echoes Player 生产版本中,为了在滚动的同时添加更多的视频,我使用 " ng-infinite-scroll "。在创建无限滚动方面它是一个非常好的、极简的,指示性的api,并且它在Echoes Player中使用非常简单。如下所示:

<div class="view-content youtube-results youtube-videos"  infinite-scroll="youtubeVideos.searchMore()"  infinite-scroll-distance="2" > .... </div>

作为一个api它有很多属性来完成无限滚动指令,但是,这次我并不使用它。

在这次投递时,我没有找到任何 angular 2的无限滚动条指令/组件。因此我认为这是一个好机会将angular 1.x中的 " ng-infinite-scroll " 指令迁移到angular 2中,并在迁移的过程中学习如何创建一个无限滚动条指令。请注意 angular 1.x的无限滚动条的源码由" coffeescript "编写。但是生产商最终准备按照ES5编译代码。

将源代码转换回JavaScript (用这个 http://js2.coffee/ ), 我开始隔离代码理解它并能够迁移到类ES2015 。

最重要的逻辑被编写为一个angular 1.x控制器. 我想这段代码应该是类 ES2015 。实际上,我想要迁移的逻辑控制器到类ES2015上,这将无关任何框架或库, 能够在任何地方使用它 ——主要应用于相同的 ponyfoo's dragula 和其他极好的组件.

但首先,我必须了解angular 2 指令的概念。

Angular 2 指令概述

在Angular 2中,除了控件我们还可以使用指令。Angular 2有许多内置的标签可以使用,例如:NgFor,NgIf,NgModel,NgClass。除此之外,还可以使用创建自定义指令的API。

本质上来说,一个指令就像是一个组件。

一共有3种类型的指令:

1. 组件 - 使用@Component()

2. 结构化指令 -使用@Directive() - 通常会改变一个元素的DOM - 例如NgIf

3. 属性指令 -使用@Directive() - 不会改变DOM,但是会添加额外的行为

无限滚动条非常适合使用 属性指令 - 它添加了一个滚动事件(行为)到一个元素并且在此元素上执行滚动。

接下来我们使用Angular 2来封装这个指令。

首先,导入相关的依赖

import { Directive, ElementRef, Input, Output, EventEmitter } from 'angular2/core'; import { Scroller } from './scroller';

逻辑和从Angular 1.x中移植的代码会从“scroller.ts”文件引入。

我们将会使用Angular 2的核心对象来定义相关的属性。

定义指令

为了声明一个属性指令,类似组件,我们使用“ @Directive() ”装饰器,在此基础上指定一个属性类选择器(即CSS选择器),示例如下:

@Directive({   selector: '[infinite-scroll]' })

指令绑定事件

接下来,我们将为这个指令定义一个类作为控制器,我们希望从元素获取一个输入数据和绑定的事件,因此这个指令将按如下方式对外开放。

export class InfiniteScroll {   @Input() set infiniteScrollDistance(distance: Number) {     this._distance = distance;   }    @Output() scroll = new EventEmitter();  //... }

这个" infiniteScrollDistance " 属性被期望从指令的外部进行设置,它将作为这个指令的一个属性API。同样地“scroll”事件将触发一个从外部绑定的方法。综合上述设定,我们将以如下方式使用这个指令:

<div class="search-results"     infinite-scroll     [infiniteScrollDistance]="2"     (scroll)="onScroll()"> </div>

注意上面“div”元素中每个属性是如何匹配指令中的响应声明的。

在Angular 2中引用指令元素

在angular 1.x的DI(依赖注入)系统中,允许我们使用 "$element" 来获取引用的DOM指令元素:

controller: function ($element) { $element.on('scroll', onScroll); }

在angular 2中,我们使用 " ElementRef " 类型定义。使用 Typescript的前提下,我们将能引用“this”上线文访问绑定的DOM指令元素的属性。

constructor(private element: ElementRef) {    // now, we can reference to: this.element }

使用ngOnInit来挂钩滚动事件到指令元素

现在,我们将使用 angular 2的钩子 — " ngOnInit " — 当指令元素已经准备就绪,钩子将运行并且一次性的初始化一个滚动器.注意我在onScroll函数上绑定"this"元素,这能保证当前滚动事件激活事件被触发者的属性时,(本文是)滚动(属性),我们能引用当前DOM指令元素的上下文。

ngOnInit() {     this.scroller = new Scroller(window, setInterval, this.element, this.onScroll.bind(this), this._distance, {});   }    private scroller: Scroller;    private _distance: Number;    onScroll() {     this.scroll.next({});   }

滚动器逻辑迁移

“scroller.ts”就是一个 ES2015的类实现 。它的大部分实现是从angular1.x的“ng-infinite-scroll”中复制过来的,它的语法符合ES2015语法规范,并尽力实现了相关更新。

结语

尽管无限滚动和原angular1.x版本中的许多特性都没有直接实现,但是,angular2中也提供了一些代替的方法,如:angular2中获取实际DOM元素的特殊语法“ this.$elementRef.nativeElement ”。

ng2开发的Echoes Player是一个开源项目。同时,你也可以fork一份ES2015规范的angular1版本的Echoes,自己完成这个项目从ES5向ES2015的迁移。

echoes-ng2旨在以angular2的更多特性完成整个项目的代码迁移。

原文  http://www.oschina.net/translate/angular-2-attribute-directive-creating-an-infinite
正文到此结束
Loading...