【问题标题】:What is an AngularJS directive?什么是 AngularJS 指令?
【发布时间】:2012-12-02 06:21:24
【问题描述】:

我花了很多时间阅读 AngularJS 文档和一些教程,我对这些文档的难以接近程度感到非常惊讶。

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

什么是 AngularJS 指令?

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

On the home page:

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

developer documentation

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

还有一个关于指令的series of talks,具有讽刺意味的是,它似乎假设观众已经理解它们是什么。

为了清晰的参考,谁能提供一个指令的精确定义来解释:

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

【问题讨论】:

  • You had me at... 以明确的 jQuery 定义为例。
  • 不确定 2012 年 Stack Overflow 上的情况如何,但我刚刚修改了这个问题并添加了“angular-directive”标签。它的tag info 实际上给出了相当明确的定义。另外,我注意到我在开发者文档中找不到第二个引用……

标签: javascript angularjs angular-directive


【解决方案1】:

它是什么(以jQuery的明确定义为例)?

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

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

它打算解决哪些实际问题和情况?

指令可以做的最强大的事情是扩展 HTML。您的扩展是用于构建应用程序的Domain Specific Language (DSL)。例如,如果您的应用程序运行在线购物站点,您可以扩展 HTML 以具有“购物车”、“优惠券”、“特价商品”等指令——在“在线购物”域,而不是“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 是什么?这就是指令。

【讨论】:

  • 马克,谢谢。我认为这很清楚,并且可能最接近准确的答案。我认为指令总是绑定到 html 标签,对吗?所以说指令是绑定到 HTML 标记的函数可能更准确。因此,它允许以声明方式扩展 HTML 语言。
  • 好吧,指令可以用在注释中,所以不是所有指令都必须绑定到 HTML 标签。例如,<!-- directive: my-directive exp -->
  • 马克,这会是对指令的非常规使用吗?即指令通常用于扩展 HTML。
  • 好的,我现在有了更好的理解。一种思考方式是:1. DSL 通常表示syntax trees 2. HTML DOM 是一棵 DSL 语法树,但它是一个刚性树:标签大多是严格设计和目的,不可扩展。 3. AngularJS 和指令机制,通过允许开发人员构建自定义树节点,使 HTML DOM 更加灵活。这些节点可以表示新的行为,或现有行为的聚合(子树)4.因此,指令允许 HTML DOM 演变为自定义 DSL
  • @MarkRajcok 我正在为你的最后一段而苦苦挣扎。普通<div></div> 是指令吗?你说是的。但是这里没有没有装饰(通过元素、类、注释、属性)。这里的人们说这些是HTML DOM 的标记。你能澄清一下吗? (我不是在谈论您可以为像<div> 这样的普通元素创建指令的原因)
【解决方案2】:

也许角度指令的真正简单和初始定义是

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

这方面的一些例子是

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

ng-model 指令绑定 HTML 控件的值(输入、 select, textarea) 到应用程序数据。

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

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

查看本教程,至少对我而言,这是对 Angular 的最佳介绍之一。更完整的方法将是 @mark-rajcok 之前所说的一切。

【讨论】:

    【解决方案3】:

    查看文档,指令是您可以编写 angularjs 解析以创建对象和行为的结构。换句话说,它是一个模板,您可以在其中混合使用任意节点和伪 javascript 和占位符来表达数据您的小部件(组件)的结构、行为方式以及数据馈送方式的意图。 然后 Angularjs 针对这些 指令 运行以将它们转换为工作的 html/javascript 代码。

    指令可以让您使用适当的语义构建更复杂的组件(小部件)。只需看一下指令的 angularjs 示例 - 他们正在定义选项卡窗格(这在常规 HTML 中当然无效)。它比使用类似 div-s 或 spans 创建结构更直观,然后将其样式设置为 看起来像选项卡窗格。

    【讨论】:

    • 我添加了我觉得技术性稍差的解释。
    • 谢谢,这很有帮助。所以也许我可以把它看成是一种动态模板(类似于 O-O 编程中的类),它封装了一个组件,通过属性和行为来描述它,能够被实例化,并且可以将自己表达到 DOM 中?它存在的原因(相对于 javascript 对象或 html 模板)是为了让 HTML 标签具有更动态的、类似对象的行为,以便它们可以开始在 O-O 类型编程中变得可操作?
    • 是和不是。我不会说 directives 存在的原因与它们在 OO 编程中的可操作性有很大关系。事实上,整个 angularjs 框架方法感觉与 HTML 和任意 DOM 节点属性密切相关,而不是编写 OO Javascript 代码。通过查看 angularjs 如何解决日常问题的所有示例,我得到了这种氛围。我想说指令背后的主要原因是有办法将行为和数据嵌入到一个语义结构化的组件中。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      首页对此很清楚: 当您将鼠标悬停在最后一部分的选项卡上时:

      我们使用自定义 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 元素,即 tabs,并让 Angular 处理这些元素的呈现。

      【讨论】:

      • 感谢您的快速回复!那么指令的目的是通过创建自定义标签和属性来扩展 HTML 的词汇?这似乎非常强大,尽管它似乎解决了比“MVW”更广泛的问题范围。顺便说一句,其他人可能不同意,但我认为滚动到页面底部,然后将鼠标悬停在一个超链接的单词上,然后阅读一个没有提到“指令”这个词的弹出工具提示并不完全是“非常清晰”的指令是什么的定义。尽管如此,非常感谢您的快速响应。
      • 是的!你可以检查他们制作的这个小提琴。实际的 html 与 html 窗格中的不同。
      猜你喜欢
      • 2017-02-04
      • 2014-03-28
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 2013-08-26
      • 2018-03-26
      • 2020-12-10
      • 2016-06-02
      相关资源
      最近更新 更多