原文链接 : How to write custom AngularJS Directive using TypeScript?
原文作者 : Siddharth Pandey
译者 : 李林璞(web前端范畴)
译者注:翻译若有疏漏,迎接指出!谢谢!转载请保存此头部。
AngularJS 框架有许多壮大的特征,个中指令(Directives)是广为人知的。在这篇文章中,我将通知你怎样用 TypeScript 编写自定义 AngularJS 指令。起首,我将讲一下关于指令的基础学问,但假如你想直接看 TypeScript 代码的,你能够跳过基础。
什么是指令?
在较高层面上,指令是一个 DOM 元素的标记(像一个属性,元素称号,解释或许 CSS 类),它通知 Angular 的 HTML 编译器(
$compiler
)去给 DOM 元素衔接一个迥殊的行动(比方经由历程事宜监听),或许以至是转变这个 DOM 元素和其子元素。Angular 本身有一些内建的指令,像
ngbind
,ngModel
和ngClass
。就像你建立控制器(controllers)和效劳(services)那样,你能够建立本身的指令给 Angular 运用。当 Angular 启动你的应用时,HTML 编译器就会对 DOM 元素举行遍历找到相符的指令。
例子
看看ng-controller
和ng-bind
这些 AngularJS 框架自带指令的运用要领:
<div ng-controller="Controller">
Hello <input ng-model='name'> <hr/>
<span data-ng-bind="name"></span> <br/>
<span ng:bind="name"></span> <br/>
<span ng_bind="name"></span> <br/>
<span data-ng-bind="name"></span> <br/>
<span x-ng-bind="name"></span> <br/>
</div>
标准化历程
上面的代码片断,有多种体式格局去标记一个指令。AngularJS 的 HTML 编译器担任决议哪一个元素婚配哪一个指令,平常经由历程辨别大小写的 camelCase
(驼峰式) 定名要领(如 ngModel
)去运用指令。然则,由于 HTML 是不辨别大小写的,平常我们运用小写情势的 短横线-分开 属性写在 DOM 元素上(如ng-model
)。
标准化历程以下:
前面的元素或属性运用带
x-
或data-
的情势。将
:
,-
或_
这些分开符转化为camelCase
(驼峰式)。
最好实践
最好运用 短横线-分开 花样(如 ng-bind
对应 ngBind
)。假如你想运用一个 HTML 考证东西,能够运用 带data前缀 的版本举行替换(如 data-ng-bind
对应 ngBind
)。上面展现的其他情势因遗留缘由依然能够运用当照样发起防止运用它们。
指令的范例
AngularJS 的 HTML 编译器如$compiler
能够基于元素名,属性,类名,另有解释去婚配指令。下面的例子展现了一个名为myDir
的指令在一个 HTML 模板里是怎样用多种体式格局去援用的:
<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>
最好实践
最好经由历程标署名或许属性而不是解释和类名去运用指令。如许做通常会更轻易去决议哪一个指令婚配给定的元素。
解释指令通常在 DOM API 限定逾越多个元素建立指令的处所运用(如table
元素)。AngularJS 1.2 采用了ng-repeat-start
和ng-repeat-end
作为处理这个题目更好的要领,勉励开发者只管运用这个要领替代解释指令。
TypeScript 中的自定义指令
让我们来建立一个只为任何的块,小部件或许人名在右侧增加题目,子题目和文本的指令。这是一个很好的例子,由于它能够在许多处所重用而且能够作为一个有断绝作用域的指令在每一个动态加载的块中作为信息展现。
来看看 HTML,Typescript 的代码在其下方:
<div class="widget-head">
<div class="page-title pull-left">{{title}}</div>
<small class="page-title-subtle" ng-show="subtitle">({{subtitle}})</small>
<div class="widget-icons pull-right"></div>
<small class="pull-right page-title-subtle" ng-show="rightText">{{rightText}}</small>
<div class="clearfix"></div>
</div>
interface IHtWidgetHeaderScope {
title: string;
subtitle: string;
rightText: string;
allowCollapse: string;
}
//Usage:
//<div ht-widget-header title="vm.map.title"></div>
// Creates:
// <div ht-widget-header=""
// title="Movie"
//</div>
class HtWidgetHeader implements ng.IDirective {
static $inject: Array<string> = [''];
constructor() { }
static instance(): ng.IDirective {
return new HtWidgetHeader();
}
scope: IHtWidgetHeaderScope = {
'title': '@',
'subtitle': '@',
'rightText': '@'
};
templateUrl: string = 'app/widgets/widget-header.html';
restrict: string = 'EA';
}
angular.module('app').directive('htWidgetHeader', HtWidgetHeader.instance);
应用 TypeScript 的特性,建立一个定义了可在指令内运用的作用域成员的接口(interface)。同样地我们想建立一个指令的实例,我们就定义一个完成了IDirective
的类(class)。
要想晓得范例定义,看看这个令人吃惊的堆栈,它收集了险些一切盛行的 JavaScript 库。这些范例定义能够让我们获得任何编译时毛病和 IDE 的智能支撑。我运用 Visual Studio 和 Visual Code,它们都对 TypeScript 有很好的支撑。
这个指令不须要任何内建的 angular 效劳或任何依靠,所以 $inject
这个静态成员只是一个空数组。假如依靠被列出来的话,框架就会依据这个变量的内容去寻觅然后依靠注入。
组织器(constructor)不必做什么事变但我们照样须要一个静态的 instance
要领去建立一个指令的实例。框架会在定义一个运用了模块指令 API 的时刻希冀一个指令的实例。
这个类的 scope
在这里非常重要,由于这个指令运用断绝的作用域,即它本身的成员变量能够在这个指令的模板当中运用但并不继续外层或其父级作用域的声明。为了可读性和可维护性,我们运用了 templateUrl
去指定模板的源码。别的,restrict
设置了指令的运用级别给元素和属性,离别运用 E 和 A 示意。
restrict
选项平常设置为:
‘A’:只婚配属性名
‘E’:只婚配元素名
‘C’:只婚配类名
‘M’:只婚配解释
这些限定只需须要都能够连系:’AEC’ 婚配属性或元素或类名。
如今能够像下面的代码片断那样运用这个指令:
<div ht-widget-header title="{{vm.title}}" subtitle="{{vm.description}}" right-text="{{vm.refreshedDateTimeInfo}}"></div>
这个指令能够在给到一个硬编码或许动态的 title
,subtitle
或许 right-text
作用域成员的情况下作为元素或许属性运用。注意到后者和任何指令一样都已被编译器标准化。上面的代码片断在一个模板里运用,该模板链接到一个含有 title
,description
和 refreshedDateTimeInfo
变量的控制器,然后展现给用户。给定一些标记和设想,就会像下面如许:
假如你想学到更多有关怎样整合 AngularJS 和 TypeScript 的学问,能够看看我的 AngularJS 文章。假如你想进修其他一些迥殊的东西能够联络我,我会尝试写相干文章的。