Heim >php教程 >PHP开发 >Detaillierte Erläuterung der Verwendung der AngularJS-Direktive

Detaillierte Erläuterung der Verwendung der AngularJS-Direktive

高洛峰
高洛峰Original
2016-12-08 10:06:391121Durchsuche

Die Beispiele in diesem Artikel beschreiben die Verwendung von AngularJS-Anweisungen. Teilen Sie es wie folgt als Referenz mit allen:

Anweisungen sind die wichtigsten Komponenten jeder AngularJS-Anwendung. Obwohl AngularJS viele Direktiven enthält, werden Sie oft feststellen, dass Sie einige spezielle Direktiven selbst erstellen müssen. Dieser Artikel führt Sie durch benutzerdefinierte Anweisungen und erklärt, wie Sie sie in realen Angular-Projekten verwenden. Am Ende des Artikels werden wir Angular-Anweisungen verwenden, um eine einfache Notizanwendung zu erstellen.

Übersicht

Eine Direktive ist etwas, das eine neue Syntax einführt. Direktiven sind Markierungen, die an DOM-Elementen vorgenommen und mit bestimmten Verhaltensweisen verknüpft werden. Statisches HTML weiß beispielsweise nicht, wie ein Datumsauswahl-Widget erstellt und angezeigt wird. Um HTML diese neue Syntax beizubringen, benötigen wir eine Direktive. Diese Anweisung erstellt ein Element, das als Datumsauswahl fungiert. Wir werden später sehen, wie wir diese Richtlinie umsetzen.

Wenn Sie schon einmal Angular-Anwendungen geschrieben haben, haben Sie bereits Direktiven verwendet, ob Sie es nun bemerkt haben oder nicht. Möglicherweise haben Sie Anweisungen wie ng-model, ng-repeat, ng-show usw. verwendet. Alle diese Anweisungen binden bestimmte Funktionen an DOM-Elemente. Beispielsweise wiederholt ng-repeat bestimmte Elemente, während ng-show Elemente bedingt anzeigt. Wenn Sie ein ziehbares Element erstellen möchten, müssen Sie möglicherweise eine Direktive erstellen. Der Grundgedanke der Richtlinie ist einfach. Es macht HTML interaktiv, indem es Ereignis-Listener an Elemente bindet und das DOM transformiert.

Betrachten Sie die Direktive aus einer jQuery-Perspektive

Überlegen Sie, wie Sie jQuery verwenden würden, um eine Datumsauswahl zu erstellen. Wir fügen zunächst ein normales Eingabefeld im HTML hinzu und rufen dann in jQuery $(element).dataPicker() auf, um es in eine Datumsauswahl umzuwandeln. Aber denken Sie darüber nach. Wenn ein Designer dieses Markup untersuchen möchte, kann er/sie dann sofort erraten, wozu dieses Feld dient? Ist es nur ein normales Eingabefeld oder eine Datumsauswahl? Um dies zu bestätigen, müssen Sie sich jQuery ansehen. Der Ansatz von Angular besteht darin, Direktiven zur Erweiterung von HTML zu verwenden. Daher könnte eine Datumsauswahlanweisung so aussehen:

<date-picker></date-picker>

oder so:

<input type=&#39;text&#39; data-picker/>

Diese Methode zum Erstellen von UI-Komponenten ist intuitiv und klar. Sie können ein Element sehen und seinen Zweck kennen.

Benutzerdefinierte Direktiven erstellen

Eine Angular-Direktive kann in vier Formen erscheinen:

1. Ein neues HTML-Element (8ea3043659788eba89a22cfe1e88c5f378d3e32b669744ae43f48110828a99d5 )

2. Attribute für ein Element (fd11e5d445701a76c4913bffa151024c)

3 ='date-picker'/>)

4. Als Kommentar (3c2a2819a37b702cc6cffcb7f91fe722)

Natürlich sind wir ganz Sie Sie können entscheiden, wie unsere Anweisungen in HTML angezeigt werden. Schauen wir uns nun an, wie eine typische Angular-Anweisung geschrieben wird. Sie ähnelt der Controller-Registrierungsmethode, gibt jedoch ein einfaches Objekt (Anweisungsdefinition) zurück, das einige Eigenschaften der Konfigurationsanweisung enthält. Der folgende Code zeigt eine einfache Hello World-Direktive:

var app = angular.module(&#39;myapp&#39;,[]);
app.directive(&#39;helloWorld&#39;,function(){
  return {
    restrict: &#39;AE&#39;,
    replace: true,
    template: &#39;<h3>Hello World!</h3>&#39;
  }
});

Im obigen Code ist die Funktion app.diretive() in unserem Modul neu registriert Befehl. Der erste Parameter dieser Funktion ist der Name der Anweisung. Der zweite Parameter ist eine Funktion, die das Direktivendefinitionsobjekt zurückgibt. Wenn Ihre Direktive Abhängigkeiten von zusätzlichen Objekten/Diensten wie $rootScope, $http oder $compile aufweist, können diese auch dort eingefügt werden. Diese Direktive kann wie folgt als HTML-Element verwendet werden:

<hello-world/>

oder:

<hello:world/>

oder als Attribut verwendet:

<div hello-world></div>

oder:

<div hello:world/>

Wenn Sie mit HTML5 kompatibel sein möchten, können Sie vor dem Attribut das Präfix x- oder data- hinzufügen. Daher stimmen die folgenden Tags mit der helloWorld-Direktive überein:

<div data‐hello‐world></div>

oder

<di vx‐hello‐world></div>

Hinweis

Beim Abgleichen von Anweisungen entfernt Angular das Präfix x- oder data- aus dem Element-/Attributnamen. Konvertieren Sie dann das Trennzeichen - oder : in die CamelCase-Notation, die der registrierten Direktive entspricht. Aus diesem Grund wird unsere helloWorld-Direktive bei Verwendung in HTML eigentlich hello-world geschrieben.

Obwohl der obige einfache Befehl nur statischen Text anzeigt, gibt es dennoch einige interessante Punkte, die es wert sind, erkundet zu werden. Wir haben in diesem Direktivendefinitionsobjekt drei Eigenschaften verwendet. Werfen wir einen Blick darauf, wofür diese drei Attribute verwendet werden:

restrict – Dieses Attribut gibt an, wie eine Direktive in HTML verwendet werden soll (denken Sie daran, dass Direktiven auf vier Arten erscheinen können). In diesem Beispiel setzen wir es auf „AE“. Daher kann diese Direktive als HTML-Element oder Attribut verwendet werden. Damit die Direktive als Klasse verwendet werden kann, können wir „restrict“ auf „AEC“ setzen.

template - 这个实行指明了当指令被Angular编译和链接时生成的HTML标记。它不一定是一个简单的字符串。template可以很复杂,其中经常会涉及其它的指令,表达式({{}}),等等。在大多数情况下你可能会想要使用templateUrl而不是template。因此,理想情况下你应该首先将模板放置在一个单独的HTML文件中然后让templateUrl指向它。

replace - 这个属性指明了是否生成的模板会代替绑定指令的元素。在前面的例子中我们在HTML中使用指令为edd05d9b720c954eda8df66606fc7d416d95f50462131a27fde32c4d9df5bdd4,并将replace属性设置为true。因此,在指令编译后,生成的模板代替了edd05d9b720c954eda8df66606fc7d416d95f50462131a27fde32c4d9df5bdd4。最后的输出结果是684271ed9684bde649abda8831d4d355Hello World!39528cedfa926ea0c01e69ef5b2ea9b0。如果你将replace设置为false,默认情况下,输出模板将会被插入到指令被调用的元素中。

link函数和作用域

有一个指令生成的模板是没有用的除非它在正确的作用域中北编译。默认情况下一个指令并不会得到一个新的子作用域。然而,它可以得到父作用域。这意味着如果一个指令位于在一个控制器中那么它将使用控制器的作用域。

为了利用作用域,我们可以使用一个叫做link的函数。它可以通过指令定义对象中的link属性来配置。我们现在对helloworld指令做一些修改一遍当用户在一个input字段中输入一个颜色名称时,Hello Wolld文字的背景颜色会自动发生改变。同样,当一个用户点击Hello World文字时,背景颜色会重置为白色。相应的HTML标记如下所示:

<body ng-controller=&#39;MainCtrl&#39;>
  <input type=&#39;text&#39; ng-model=&#39;color&#39; placeholder=&#39;Enter a color&#39; / >
  <hello-wolrd/>
</body>

   

修改后的helloWorld指令代码如下所示:

app.directive(&#39;helloWorld&#39;,function(){
  return {
    restrict: &#39;AE&#39;,
    replace: true,
    template: &#39;<p style="background-color:{{color}}"></p>&#39;,
    link: function(scope,elem,attr){
      elem.bind(&#39;click&#39;,function(){
        elem.css(&#39;background-color&#39;,&#39;white&#39;);
      scope.$apply(function(){
        scope.color = "white";
      });
      });
      elem.bind(&#39;mouseover&#39;,function(){
        elem.css(&#39;cursor&#39;,&#39;pointer&#39;);
      });
    }
  }
});

   

注意到link函数被用在了指令中。它接收三个参数:

scope - 它代表指令被使用的作用域。在上面的例子中它等同于符控制器的作用域。

elem - 它代表绑定指令的元素的jQlite(jQuery的一个自己)包裹元素。如果你在AngularJS被包含之前就包括了jQuery,那么它将变成jQuery包裹元素。由于该元素已经被jQuery/jQlite包裹,我们没有必要将它包含在$()中来进行DOM操作。

attars - 它代表绑定指令的元素上的属性。例如,如果你在HTML元素上有一些指令形式为:5525e9281c68be71aaa8c5ced5bd1dc56d95f50462131a27fde32c4d9df5bdd4,你可以在link函数内用attrs.someAttribute来引用这些属性。

link函数主要是用来对DOM元素绑定事件监听器,监视模型属性变化,并更新DOM。在前面的指令代码中,我们绑定了两个监听器,click和mouseover。click处理函数重置了

的背景颜色,而mouseover处理函数则将游标改变为pointer。模板中拥有表达式{{color}},它将随着父作用域中的模型color的变化而变化,从而改变了Hello World的背景色。

Compile函数

Compile函数主要用来在link函数运行之前进行一些DOM转化。它接收下面几个参数:

tElement - 指令绑定的元素

attrs - 元素上声明的属性

这里要注意compile不能够访问scope,而且必须返回一个link函数。但是,如果没有compile函数以依然可以配置link函数。compile函数可以被写成下面的样子:

app.directive(&#39;test&#39;,function(){
  return {
    compile: function(tElem,attrs){
      //在这里原则性的做一些DOM转换
      return function(scope,elem,attrs){
       //这里编写link函数
      }
    }
  }
});

   

大多数时候,你仅仅只需要编写link函数。这是因为大部分指令都只关心与注册事件监听器,监视器,更新DOM等等,它们在link函数中即可完成。像是ng-repeat这样的指令,需要多次克隆并重复DOM元素,就需要在link函数运行之前使用compile函数。你可能会问威慑呢么要将两个函数分别使用。为什么我们不能只编写一个函数?为了回答这个问题我们需要理解Angular是如何编译指令的!

指令是如何被编译的

当应用在启动时,Angular开始使用$compile服务解析DOM。这项服务会在标记中寻找指令然后将它们各自匹配到注册的适龄。一旦所有的指令都已经被识别完成,Angular就开始执行它们的compile函数。正如前面所提到的,compile函数返回一个link函数,该函数会被添加到稍后执行的link函数队列中。这叫做编译阶段(compile phase)。注意到即使同一个指令有几个实例存在,compile函数也只会运行一次。

在编译阶段之后就到了链接阶段(link phase),这时link函数就一个接一个的执行。在这个阶段中模板被生成,指令被运用到正确的作用域,DOM元素上开始有了事件监听器。不像是compile函数,lin函数会对每个指令的实例都执行一次。

改变指令的作用域

默认情况下指令应该访问父作用域。但是我们并不像对所有情况一概而论。如果我们对指令暴露了父控制器的scope,那么指令就可以自由的修改scope属性。在一些情况下你的指令可能想要添加一些只有内部可以使用的属性和函数。如果我们都在父作用域中完成,可能会污染了父作用域。因此,我们有两种选择:

一个子作用域 - 这个作用域会原型继承父作用域。

一个隔离的作用域 - 一个全新的、不继承、独立存在的作用域。

作用域可以由指令定义对象中的scope属性定义。下面的例子展示了这一点:

app.directive(&#39;helloWorld&#39;,function(){
  return {
    scope: true, //使用一个继承父作用域的自作用域
    restrict: &#39;AE&#39;,
    replace: true,
    template: &#39;<h3>Hello World!</h3>&#39;
  }
});

   

上面的代码要求Angular为指令提供一个能够原型继承父作用域的子组用于。另一种情形,一个隔离作用域,代码如下所示:

app.directive(&#39;helloWorld&#39;,function(){
  return {
    scope: {}, //使用一个全新的隔离作用域
    restrict: &#39;AE&#39;,
    replace: true,
    template: &#39;<h3>Hello World!</h3>&#39;
  }
});

   

上面的指令使用一个不继承父作用域的全新隔离作用域。当你想要创建一个可重用的组件时隔离作用域是一个很好的选择。通过隔离作用域我们确保指令是自包含的兵可以轻松地插入到任何HTML app中。这种做法防止了父作用域被污染,由于它不可访问父作用域。在我们修改后的helloWorld指令中如果你将scope设置为{},那么代码就不会再正常运行。它将创建一个隔离的作用域然后表达式{{color}}将无法引用隔离作用域中的属性因此值变为undefined。

隔离作用域并不意味着你一点都不能获取到父作用域中的属性。有一些技巧可以使你访问父作用域中的属性同时监听这些属性的变化。我们将在后续文章中提到这种高级技巧。


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn