本文实例讲述了AngularJS指令用法。分享给大家供大家参考,具体如下:
指令(directives)是任何AngularJS应用中最重要的成分。尽管AngularJS已经自带了很多指令,你经常会发现需要自己亲手创建一些特别的指令。本文将会带你了解自定义指令并解释如何在现实世界中的Angular项目中使用它们。文章的最后,我们将一起用Angular指令来创建一个简单的笔记小应用。
综述
一个指令就是一个引入新语法的东西。指令是在DOM元素上做的标记,并同时附加了一些特定的行为。例如,静态的HTML并不知道如何来创建并显示一个日期选择插件。为了将这个新语法教给HTML我们需要一条指令。这个指令将会创建一个充当日期选择器的元素。我们将在随后看到如何实现这个指令。
如果你之前已经编写过Angular应用,那么你已经使用过指令了,不管你有没有意识到这点。你可能已经使用过像是ng-model,ng-repeat,ng-show等等这样的指令。所有这些指令都将特定的功能绑定到了DOM元素之上。例如,ng-repeat会重复特定的元素,而ng-show会有条件的展示元素。如果你想要创建一个可拖动元素的话你可能需要创建一个指令。指令背后的基本思想很简单。它通过在元素上绑定事件监听器并且将DOM变形来使HTML变得具有交互性。
从jQuery的角度来看指令
想想你如何使用jQuery来创建一个日期选择器。我们首先在HTML中添加一个普通的input字段然后在jQuery中我们调用$(element).dataPicker()来将其转换为一个日期选择器。但是,考虑一下。当一个设计师想要来检查这个标记时,他/她能够立刻猜出这个字段究竟是干什么用的吗?它仅仅是一个普通的input字段还是一个日期选择器?你必须要查看jQuery来确认这点。Angular的方法是使用指令来扩展HTML。因此,一个日期选择器的指令看上去可能如下所示:
<date-picker></date-picker></div>
或者如下所示:
<input type='text' data-picker/></div>
这种创建UI成分的方法既直观又清楚。你可以看到元素就知道它的用途。
创建自定义指令
一个Angular指令可能以四种形式出现:
1.一个新的HTML元素(<date-picker></date-picker>)
2.一个元素上的属性(<input type='text' date-picker/>)
3.作为一个类(<input type='text' class='date-picker'/>)
4.作为注释(<!--directive:date-picker-->)
当然,我们完全可以决定我们的指令以什么形式出现在HTML中。现在,我们来看看一个典型的Angular指令是如何写成的。它和controller的注册方式类似,但是它会返回一个简单的对象(指令定义),其中那个包含有一些配置指令的属性。下面的代码展示了一个简单和Hello World指令:
var app = angular.module('myapp',[]); app.directive('helloWorld',function(){ return { restrict: 'AE', replace: true, template: '<h3>Hello World!</h3>' } });</div>
在上面的代码中,app.diretive()函数在我们的模块中注册了一个新的指令。这个函数的第一个参数是指令的名称。第二个参数是一个返回指令定义对象的函数。如果你的指令对额外的对象/服务(services)例如 $rootScope, $http 或者 $compile 有依赖,它们也可以在其中被注入。这个指令可以作为一个HTML元素来使用,如下所示:
<hello-world/></div>
或者:
<hello:world/></div>
或者作为一个属性来使用:
<div hello-world></div></div>
或者:
<div hello:world/></div>
如果你想要兼容HTML5,你可以在属性前面加上x-或者data-前缀。因此,下面的标记将会匹配helloWorld指令:
<div data‐hello‐world></div></div>
或者
<di vx‐hello‐world></div></div>
注意
当匹配指令时,Angular会从元素/属性名之前去除前缀x-或者data-。然后将分隔符 - 或者 : 转换为驼峰表示法已匹配注册的指令。这就是为什么我们的helloWorld指令用在HTML中的时候实际上写成了hello-world。
尽管上面的这个简单的指令仅仅只是展示了一些静态的文本,其中还是有一些值得我们去探究的有趣的点。我们已经在这个指令定义对象中使用了三个属性。我们来看看这三个属性分别都有什么用:
restrict - 这个属性指明了一个指令应该如何在HTML中使用(记住指令可以以四种方式出现)。在这个例子中我们将它设置为'AE'。因此,这条指令可以作为一个HTML元素或者一个属性来使用。为了允许指令作为一个类来使用我们可以将restrict设置为'AEC'。
template - 这个实行指明了当指令被Angular编译和链接时生成的HTML标记。它不一定是一个简单的字符串。template可以很复杂,其中经常会涉及其它的指令,表达式({{}}),等等。在大多数情况下你可能会想要使用templateUrl而不是template。因此,理想情况下你应该首先将模板放置在一个单独的HTML文件中然后让templateUrl指向它。
replace - 这个属性指明了是否生成的模板会代替绑定指令的元素。在前面的例子中我们在HTML中使用指令为<hello-world></hello-world>,并将replace属性设置为true。因此,在指令编译后,生成的模板代替了<hello-world></hello-world>。最后的输出结果是<h3>Hello World!</h3>。如果你将replace设置为false,默认情况下,输出模板将会被插入到指令被调用的元素中。
link函数和作用域
有一个指令生成的模板是没有用的除非它在正确的作用域中北编译。默认情况下一个指令并不会得到一个新的子作用域。然而,它可以得到父作用域。这意味着如果一个指令位于在一个控制器中那么它将使用控制器的作用域。
为了利用作用域,我们可以使用一个叫做link的函数。它可以通过指令定义对象中的link属性来配置。我们现在对helloworld指令做一些修改一遍当用户在一个input字段中输入一个颜色名称时,Hello Wolld文字的背景颜色会自动发生改变。同样,当一个用户点击Hello World文字时,背景颜色会重置为白色。相应的HTML标记如下所示:
<body ng-controller='MainCtrl'> <input type='text' ng-model='color' placeholder='Enter a color' / > <hello-wolrd/> </body></div>
修改后的helloWorld指令代码如下所示:
app.directive('helloWorld',function(){ return { restrict: 'AE', replace: true, template: '<p style="background-color:{{color}}"></p>', link: function(scope,elem,attr){ elem.bind('click',function(){ elem.css('background-color','white'); scope.$apply(function(){ scope.color = "white"; }); }); elem.bind('mouseover',function(){ elem.css('cursor','pointer'); }); } } });</div>
注意到link函数被用在了指令中。它接收三个参数:
scope - 它代表指令被使用的作用域。在上面的例子中它等同于符控制器的作用域。
elem - 它代表绑定指令的元素的jQlite(jQuery的一个自己)包裹元素。如果你在AngularJS被包含之前就包括了jQuery,那么它将变成jQuery包裹元素。由于该元素已经被jQuery/jQlite包裹,我们没有必要将它包含在$()中来进行DOM操作。
attars - 它代表绑定指令的元素上的属性。例如,如果你在HTML元素上有一些指令形式为:<hello-world some-attribute></hello-world>,你可以在link函数内用attrs.someAttribute来引用这些属性。
link函数主要是用来对DOM元素绑定事件监听器,监视模型属性变化,并更新DOM。在前面的指令代码中,我们绑定了两个监听器,c