什么是AngularJS指令?

185

我花了很多时间阅读AngularJS文档和一些教程,但是我对文档的使用方式感到非常不友好。

我有一个简单、可以回答的问题,这个问题也可能对其他想学习AngularJS的人有用:

什么是AngularJS指令?

应该有一个简单、精确的指令定义,但是AngularJS网站提供了这些令人惊讶的无用定义:

在主页上:

指令是AngularJS中一个独特而强大的功能。指令让您发明新的HTML语法,特定于您的应用程序。

开发者文档中:

指令是教HTML新技巧的一种方法。在DOM编译期间,将指令与HTML匹配并执行。这允许指令注册行为或转换DOM。

还有一系列关于指令的讲座,具有讽刺意味的是,这些讲座似乎假定听众已经了解它们是什么。

是否有人能够提供一个清晰的参考,准确地定义指令,解释:

  1. 它是什么(以jQuery的明确定义为例)
  2. 它旨在解决哪些实际问题和情况
  3. 它体现的设计模式,或者说它如何适应AngularJS所声称的MVC/MVW使命。

2
你让我想起了... 以 jQuery 的清晰定义为例子。 - user3451822
不确定2012年在Stack Overflow上是怎样的,但我刚刚修改了这个问题并添加了“angular-directive”标签。它的标签信息实际上给出了相当清晰的定义。此外,我注意到在开发者文档中找不到第二个引用。 - Sebastian Simon
5个回答

144

它是什么(以jQuery的清晰定义为例)?

指令本质上是一个函数,当Angular编译器在DOM中找到它时执行。这个函数可以做几乎任何事情,这就是为什么我认为很难定义指令的原因。每个指令都有一个名称(例如ng-repeat、tabs、make-up-your-own),并确定它可以在哪里使用:元素、属性、类、注释。

通常,指令只有一个(后置)链接函数。复杂的指令可能有编译函数、前置链接函数和后置链接函数。

它旨在解决哪些实际问题和情况?

指令最强大的功能是扩展HTML。您的扩展是用于构建应用程序的领域特定语言(DSL)。例如,如果您的应用程序运行在线购物网站,您可以扩展HTML以具有“shopping-cart”、“coupon”、“specials”等指令 - 任何在“在线购物”领域内更自然使用的单词、对象或概念,而不是“div”和“span”(正如@WTK已经提到的那样)。

指令还可以将HTML组件化-将一堆HTML组合成可重用的组件。如果您发现自己正在使用ng-include来拉取大量HTML,则可能是重构为指令的时候了。

它体现了哪种设计模式,或者说它如何符合AngularJS所谓的MVC/MVW使命?

指令是您操作DOM并捕获DOM事件的地方。这就是为什么指令的编译和链接函数都会接收“元素”作为参数的原因。您可以:

  • 定义一堆HTML(即模板),以替换指令
  • 将事件绑定到此元素(或其子元素)
  • 添加/删除类
  • 更改text()值
  • 观察在同一元素中定义的属性的更改(实际上是观察属性的值-这些是作用域属性,因此指令会监视“模型”的更改)
  • 等等。
在HTML中,我们有像<a href="..."><img src="..."><br><table><tr><th>这样的东西。您会如何描述a、href、img、src、br、table、tr和th是什么?这就是指令的作用。

2
马克,谢谢。我认为这很清楚,也可能是最接近准确答案的。我认为指令总是绑定到HTML标签上,对吗?因此,也许更准确地说,指令是绑定到HTML标签的函数。因此,它允许以声明方式扩展HTML语言。 - tohster
好的,指令可以用在注释中,因此并不是所有指令都必须绑定到HTML标签上。例如:<!-- directive: my-directive exp --> - Mark Rajcok
马克,那是一种非常规的指令使用方式吗?也就是说,指令通常用于扩展HTML。 - tohster
9
好的,我现在理解得更好了。可以这样想: 1. DSL通常代表语法树2. HTML DOM是一个DSL语法树,但它是一个刚性的语法树:标签大多被严格设计和用途,不可扩展。 3. AngularJS和指令机制使HTML DOM更加灵活,允许开发人员构建自定义的树节点。这些节点可以代表新的行为或现有行为的聚合(子树)。 4. 因此,指令允许HTML DOM进化成为一个定制的DSL。 - tohster
1
@MarkRajcok,我对你最后一段话感到困惑。普通的<div></div>是一个指令吗?你说是,但这里没有任何装饰(通过元素、类、注释、属性)。这些只是HTML DOM的标记。你能澄清一下吗?(我不是在谈论可以为普通元素如<div>创建指令的情况) - Royi Namir
显示剩余2条评论

11

对于 Angular 指令来说,也许一个非常简单和最初的定义是:

AngularJS 指令 (ng-directives) 是具有 ng 前缀的 HTML 属性 (ng-model、ng-app、ng-repeat、ng-bind),Angular 使用它们来扩展 HTML。(来源:W3schools angular 教程

其中一些示例包括:

ng-app 指令定义了一个 AngularJS 应用程序。

ng-model 指令将 HTML 控件(输入、选择、文本区域)的值绑定到应用程序数据。

ng-bind 指令将应用程序数据绑定到 HTML 视图。

<div ng-app="">
    <p>Name: <input type="text" ng-model="name"></p>
    <p ng-bind="name"></p>
</div>

看看这个教程,至少对我来说它是Angular最好的入门介绍之一。更全面的方法是@mark-rajcok之前所说的一切。


4
看文档,指令是您可以编写的结构,angularjs解析它们以创建对象和行为。换句话说,它是一个模板,在其中您使用任意节点和伪JavaScript的混合以及用于数据的占位符来表达您的小部件(组件)的结构、行为和数据馈送意图。然后,Angularjs针对这些指令运行,将它们转换为工作的html / javascript代码。
指令的存在是为了让您使用适当的语义构建更复杂的组件(小部件)。只需看看angularjs指令的示例-它们定义了选项卡窗格(在常规HTML中当然无效)。与使用div或span创建结构并将其样式化以“看起来像”选项卡窗格相比,它更直观。

我添加了我认为略微不太技术性的解释。 - raam86
1
谢谢,这非常有帮助。那么我可以把它看作是一种动态模板(类似于面向对象编程中的类),它封装了一个组件,通过属性和行为来描述它,能够被实例化,并且可以表达自己到DOM?它存在的原因(与JavaScript对象或HTML模板相比)是允许HTML标签具有更多的动态、对象式的行为,以便它们可以开始在面向对象类型的编程中变得可操作? - tohster
是的和不是的。我不会说指令存在的原因与它们在OO编程中可操作性有很大关系。事实上,整个angularjs框架的方法感觉与HTML和任意DOM节点属性密切相关,而不是编写OO Javascript代码。从查看angularjs如何解决日常问题的所有示例中,我可以感受到这种氛围。我会说指令背后的主要原因是为了在一个语义化结构化的组件中嵌入行为和数据的方式。 - WTK

3
在AngularJS中,指令是HTML DOM元素的标记,例如属性(restrict-A)、元素名(restrict-E)、注释(restrict-M)或CSS类(restrict-C),它们告诉AngularJS的HTML编译器($compile)对该DOM元素执行指定行为,甚至是转换DOM元素及其子元素。一些示例包括ng-bind、ng-hide/show等。

2
首页非常清晰地表明了这一点: 当您悬停在最后一个部分的选项卡上时:
我们使用自定义标签tabs扩展了HTML词汇。 tabs抽象出了渲染选项卡所需的复杂HTML结构和行为。结果是更易读的视图和非常容易重用的语法。
然后在下一个选项卡中:
angular.module('components', []).
  directive('tabs', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: {},
      controller: function($scope, $element) {
        var panes = $scope.panes = [];

        $scope.select = function(pane) {
          angular.forEach(panes, function(pane) {
            pane.selected = false;
          });
          pane.selected = true;
        }

因此,您可以发明HTML元素,例如标签页,让Angular处理这些元素的呈现。


2
感谢您的快速回复!那么指令的目的是通过创建自定义标签和属性来扩展HTML的词汇表?这似乎非常强大,尽管它似乎解决的问题范围比“MVW”要广泛得多。顺便说一句,其他人可能不同意,但我认为滚动到页面底部,然后悬停在超链接单词上,然后阅读一个从未提到过“指令”一词的弹出工具提示并不完全是“非常清晰”的指令定义。尽管如此,非常感谢您的迅速回复。 - tohster
是的!您可以检查他们制作的这个fiddle。 实际的HTML与HTML窗格中的不同。 - raam86

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接