ホームページ  >  記事  >  ウェブフロントエンド  >  AngularJs を学ぶ: ディレクティブ命令の使用法 (完全版)_AngularJS

AngularJs を学ぶ: ディレクティブ命令の使用法 (完全版)_AngularJS

WBOY
WBOYオリジナル
2016-05-16 15:03:481967ブラウズ

このチュートリアルでは AngularJs バージョン 1.5.3 を使用します

AngularJs GitHub: https://github.com/angular/angular.js/

AngularJs のダウンロード アドレス: https://angularjs.org/

概要: ディレクティブ (命令) は、AngularJ の非常に強力で便利な機能の 1 つだと思います。これは、パブリックのカスタム DOM 要素や CLASS 属性、または ATTR 属性を記述することに相当しますが、それだけではなく、それを基にスコープを操作したり、イベントをバインドしたり、スタイルを変更したりすることもできます。このディレクティブを通じて、ページング命令、オートコンプリート命令など、多くのパブリック命令をカプセル化できます。 HTML ページに 1 行のコードを記述するだけで、多くの強力な機能を実現できます。一般に、ディレクティブは次の状況で使用する必要があります:
1. HTML をよりセマンティックにすると、コードやロジックを詳しく調べなくても、ページの一般的なロジックを知ることができます。
2. カスタム コンポーネントを抽象化し、別の場所で再利用します。

1. ディレクティブの定義と使用方法
AngularJs のディレクティブ定義はおおよそ次のとおりです

angular.module("app",[]).directive("directiveName",function(){ 
 return{ 
 //通过设置项来定义 
 }; 
}) 

ディレクティブは、要素名、属性、クラス、コメントに配置できます。以下は、myDir ディレクティブを参照する同等の方法です。 (ただし、多くのディレクティブは「属性」の使用に限定されています)

<span <span style="font-family: Arial, Helvetica, sans-serif;">directive-name</span><span style="font-family: Arial, Helvetica, sans-serif;">="exp"></span>//属性</span> 
 
<span class="<span style="font-family: Arial, Helvetica, sans-serif;">directive-name</span>: exp;"></span>//class 
 
<<span style="font-family: Arial, Helvetica, sans-serif;">directive-name</span>></<span style="font-family: Arial, Helvetica, sans-serif;">directive-name</span>>//元素 
 
<!-- directive: <span style="font-family: Arial, Helvetica, sans-serif;">directive-name </span><span style="font-family: Arial, Helvetica, sans-serif;">exp -->//注释</span> 

以下は例です:

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<hello-world></hello-world> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.directive('helloWorld', function() { 
 return { 
 restrict: 'E', 
 template: '<div>Hi 我是林炳文~~~</div>', 
 replace: true 
 }; 
}); 
</script> 
</html> 

結果:


以下はディレクティブの詳細版です

var myModule = angular.module(...); 
 
myModule.directive('directiveName', function factory(injectables) { 
 
 var directiveDefinitionObject = { 
 
   priority: 0, 
 
   template: '<div></div>', 
 
   templateUrl: 'directive.html', 
 
   replace: false, 
 
   transclude: false, 
 
   restrict: 'A', 
 
   scope: false, 
 
   compile: function compile(tElement, tAttrs, transclude) { 
 
     return { 
 
       pre: function preLink(scope, iElement, iAttrs, controller) { ... }, 
 
       post: function postLink(scope, iElement, iAttrs, controller) { ... } 
 
    } 
 
  }, 
 
   link: function postLink(scope, iElement, iAttrs) { ... } 
 
}; 
 
 return directiveDefinitionObject; 
 
}); 

2. 指令内容の解釈
8つのコンテンツがあることがわかります
1.制限
(文字列) オプションのパラメータ。DOM で命令がどのような形式で宣言されているかを示します。値は次のとおりです: E (要素)、A (属性)、C (クラス)、M (コメント)。デフォルト値は A です。 ; もちろん、EA など、2 つを組み合わせて使用​​することもできます。
[html] プレーンコピーを表示 私のコードスニペットから派生した CODE のコードスニペットを表示
E (要素): 016295347a3029e43311286ccfe10e1a68fd79fd4af1df9fbd3916fd6ab1c606 A (属性):35fd8d48ae58d47fe676c7fa589a08aa16b28748ea4df4d9c2150843fecfba68
C (クラス): c9319480cb6dde66254d6e5a18255f6c16b28748ea4df4d9c2150843fecfba68
M (コメント): 52c9fdafe7d2e5af494c2a09439f0be5 一般的にはE/A/Cの方が多く使われます。


2.優先度
(数字)、命令の優先順位を示すオプションのパラメーター。単一の DOM に複数の命令がある場合、優先順位の高い命令が最初に実行されます。

3.ターミナル

(ブール値) はオプションのパラメータで、true または false に設定できます。true に設定すると、この命令よりも優先度の低い他の命令は無効になり、呼び出されなくなります (同じ優先度を持つ命令)。引き続き実行されます)

4.テンプレート (文字列または関数) のオプションのパラメータ。次のものが可能です:

(1) HTML テキストの一部

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<hello-world></hello-world> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.directive('helloWorld', function() { 
 return { 
 restrict: 'E', 
 template: '<div><h1>Hi 我是林炳文~~~</h1></div>', 
 replace: true 
 }; 
}); 
</script> 
</html> 

(2) 2 つのパラメータ tElement と tAttrs を受け取る関数 このうち、tElement はこの命令を使用する要素を指し、tAttrs はインスタンスの属性であり、

など、要素上のすべての属性で構成されるコレクション (オブジェクト) です。 9250c29de816ebe02299e187242f53d21e1283272b9f904b0d566db0f51327df

ここで、title は tattrs
の属性です。
テンプレートが関数の場合に何が起こるかを見てみましょう

結果:
<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<hello-world></hello-world> 
<hello-world2 title = '我是第二个directive'></hello-world2> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.directive('helloWorld', function() { 
 return { 
 restrict: 'E', 
 template: '<div><h1>Hi 我是林炳文~~~</h1></div>', 
 replace: true 
 }; 
}); 
app.directive("helloWorld2",function(){ 
 return{ 
 restrict:'EAC', 
 template: function(tElement,tAttrs){ 
 var _html = ''; 
 _html += '<div>' +'hello '+tAttrs.title+'</div>'; 
 return _html; 
 } 
 }; 
 }); 
</script> 
</html> 

hello-world2 のタグ内の title フィールドが命令でも使用されていることがわかります

5.templateUrl (文字列または関数)、オプションのパラメータは

にすることができます (1) HTML ファイルのパスを表す文字列
(2) tElement と tAttrs の 2 つのパラメータを受け取る関数 (上記とほぼ同じ)

注: ローカルで開発する場合は、サーバーを実行する必要があります。そうでない場合、templateUrl を使用すると、クロス オリジン リクエスト スクリプト (CORS) エラーが報告されます。 HTML テンプレートは非同期で読み込まれるため、大量のテンプレートを読み込むと Web サイトの速度が低下します。ここでのトリックは、最初にテンプレートをキャッシュすることです

インデックス ページが読み込まれた後、ページの一部として次のコードを含めることができます。


这里的id属性就是被设置在templateUrl上用的。

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<hello-world></hello-world> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.directive('helloWorld', function() { 
 return { 
 restrict: 'E', 
 templateUrl: 'hello.html', 
 replace: true 
 }; 
}); 
</script> 
<script type='text/ng-template' id='hello.html'> 
 <div><h1>Hi 我是林炳文~~~</h1></div> 
</script> 
</html> 

输出结果:


另一种办法缓存是:

app.run(["$templateCache", function($templateCache) { 
 $templateCache.put("hello.html", 
 "<div><h1>Hi 我是林炳文~~~</h1></div>"); 
}]); 

使用实例如下:

 
 
 
  
 AngularJS入门学习 
  
 
 
 
 
 
 

结果:


 其实第一种方法还好一些,写起来会比较快,笔者就得最多的也是第一种写法,直接包在scprit当中

 6.replace
(布尔值),默认值为false,设置为true时候,我们再来看看下面的例子(对比下在template时候举的例子)

                

 replace为true时,hello-world这个标签不在了,反之,则存在。

7.scope
(1)默认值false。表示继承父作用域;

(2)true。表示继承父作用域,并创建自己的作用域(子作用域);

(3){}。表示创建一个全新的隔离作用域;

7.1首先我们先来了解下scope的继承机制。我们用ng-controller这个指令举例,

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<div ng-controller='MainController'> 
 父亲:{{name}}<input ng-model="name" /> 
 <div my-directive></div> 
 </div> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.controller('MainController', function ($scope) { 
 $scope.name = '林炳文'; 
}); 
app.directive('myDirective', function () { 
 return { 
 restrict: 'EA', 
 scope:false, 
 template: '<div>儿子:{{ name }}<input ng-model="name"/></div>' 
 }; 
}); 
</script> 
</html> 

接下来我们通过一个简单明了的例子来说明scope取值不同的差别:

scope:false

scope:true

scope:{}

当为false时候,儿子继承父亲的值,改变父亲的值,儿子的值也随之变化,反之亦如此。(继承不隔离)

当为true时候,儿子继承父亲的值,改变父亲的值,儿子的值随之变化,但是改变儿子的值,父亲的值不变。(继承隔离)

当为{}时候,没有继承父亲的值,所以儿子的值为空,改变任何一方的值均不能影响另一方的值。(不继承隔离)

tip:当你想要创建一个可重用的组件时隔离作用域是一个很好的选择,通过隔离作用域我们确保指令是‘独立'的,并可以轻松地插入到任何HTML app中,并且这种做法防止了父作用域被污染;
7.2隔离作用域可以通过绑定策略来访问父作用域的属性。
directive 在使用隔离 scope 的时候,提供了三种方法同隔离之外的地方交互。这三种分别是

@ 绑定一个局部 scope 属性到当前 dom 节点的属性值。结果总是一个字符串,因为 dom 属性是字符串。
& 提供一种方式执行一个表达式在父 scope 的上下文中。如果没有指定 attr 名称,则属性名称为相同的本地名称。
= 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。

@ 局部 scope 属性

@ 方式局部属性用来访问 directive 外部环境定义的字符串值,主要是通过 directive 所在的标签属性绑定外部字符串值。这种绑定是单向的,即父 scope 的绑定变化,directive 中的 scope 的属性会同步变化,而隔离 scope 中的绑定变化,父 scope 是不知道的。

如下示例:directive 声明未隔离 scope 类型,并且使用@绑定 name 属性,在 directive 中使用 name 属性绑定父 scope 中的属性。当改变父 scope 中属性的值的时候,directive 会同步更新值,当改变 directive 的 scope 的属性值时,父 scope 无法同步更新值。

js 代码:

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<div ng-controller="myController"> 
 <div class="result"> 
 <div>父scope: 
 <div>Say:{{name}}<br>改变父scope的name:<input type="text" value="" ng-model="name"/></div> 
 </div> 
 <div>隔离scope: 
 <div isolated-directive name="{{name}}"></div> 
 </div> 
 <div>隔离scope(不使用父scope {{name}}): 
 <div isolated-directive name="name"></div> 
 </div> 
 </div> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
 app.controller("myController", function ($scope) { 
 $scope.name = "hello world"; 
 }).directive("isolatedDirective", function () { 
 return { 
 scope: { 
 name: "@" 
 }, 
 template: 'Say:{{name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">' 
 }; 
}); 
</script> 
</html> 

结果:页面初始效果

动画效果:


可以看到父scope上的内容发生改变,子scope同时发生改变。而子scope上的内容发生改变。不影响父scope上的内容!

= 局部 scope 属性

= 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。
意思是,当你想要一个双向绑定的属性的时候,你可以使用=来引入外部属性。无论是改变父 scope 还是隔离 scope 里的属性,父 scope 和隔离 scope 都会同时更新属性值,因为它们是双向绑定的关系。

示例代码:

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
<div ng-controller="myController"> 
 <div>父scope: 
 <div>Say:{{user.name}}<br>改变父scope的name:<input type="text" value="" ng-model="userBase.name"/></div> 
 </div> 
 <div>隔离scope: 
 <div isolated-directive user="userBase"></div> 
 </div> 
</div> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
 app.controller("myController", function ($scope) { 
 $scope.userBase = { 
 name: 'hello', 
 id: 1 
 }; 
 }).directive("isolatedDirective", function () { 
 return { 
 scope: { 
 user: "=" 
 }, 
 template: 'Say:{{user.name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="user.name"/>' 
 } 
 }) 
</script> 
</html> 

效果:

可以看到父scope和子scope上的内容一直都是一样的!
& 局部 scope 属性

& 方式提供一种途经是 directive 能在父 scope 的上下文中执行一个表达式。此表达式可以是一个 function。
比如当你写了一个 directive,当用户点击按钮时,directive 想要通知 controller,controller 无法知道 directive 中发生了什么,也许你可以通过使用 angular 中的 event 广播来做到,但是必须要在 controller 中增加一个事件监听方法。
最好的方法就是让 directive 可以通过一个父 scope 中的 function,当 directive 中有什么动作需要更新到父 scope 中的时候,可以在父 scope 上下文中执行一段代码或者一个函数。

如下示例在 directive 中执行父 scope 的 function。

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<body> 
 <div ng-controller="myController"> 
 <div>父scope: 
 <div>Say:{{value}}</div> 
 </div> 
 <div>隔离scope: 
 <div isolated-directive action="click()"></div> 
 </div> 
</div> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
 app.controller("myController", function ($scope) { 
 $scope.value = "hello world"; 
 $scope.click = function () { 
 $scope.value = Math.random(); 
 }; 
 }).directive("isolatedDirective", function () { 
 return { 
 scope: { 
 action: "&" 
 }, 
 template: '<input type="button" value="在directive中执行父scope定义的方法" ng-click="action()"/>' 
 } 
 }) 
</script> 
</html> 

效果:


指令的内容比较多,下面再来讲讲transclude、compline、link、contrller

8.transclude
 如果不想让指令内部的内容被模板替换,可以设置这个值为true。一般情况下需要和ngTransclude指令一起使用。 比如:template:"dc6dce4a544fdca2df29d5ac0ea9906bhello every 144e86f8e6a2df8d24469044d39968c016b28748ea4df4d9c2150843fecfba6816b28748ea4df4d9c2150843fecfba68",这时,指令内部的内容会嵌入到ng-transclude这个div中。也就是变成了dc6dce4a544fdca2df29d5ac0ea9906bhello every dc6dce4a544fdca2df29d5ac0ea9906b这是指令内部的内容16b28748ea4df4d9c2150843fecfba6816b28748ea4df4d9c2150843fecfba68。默认值为false;这个配置选项可以让我们提取包含在指令那个元素里面的内容,再将它放置在指令模板的特定位置。当你开启transclude后,你就可以使用ng-transclude来指明了应该在什么地方放置transcluded内容

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
<div sidebox title="Links"> 
  <ul> 
  <li>First link</li> 
  <li>Second link</li> 
  </ul> 
</div> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.directive('sidebox', function() { 
 return { 
 restrict: 'EA', 
 scope: { 
  title: '@' 
 }, 
 transclude: true, 
 template: '<div class="sidebox">\ 
  <div class="content">\ 
  <h2 class="header">{{ title }}</h2>\ 
  <span class="content" ng-transclude>\ 
  </span>\ 
  </div>\ 
 </div>' 
 }; 
}); 
</script> 
</html> 

结果:

当  transclude: false,时

如果指令使用了transclude参数,那么在控制器无法正常监听数据模型的变化了。建议在链接函数里使用$watch服务。
9.controller
可以是一个字符串或者函数。

若是为字符串,则将字符串当做是控制器的名字,来查找注册在应用中的控制器的构造函数

angular.module('myApp', []) 
.directive('myDirective', function() { 
restrict: 'A', // 始终需要 
controller: 'SomeController' 
}) 
// 应用中其他的地方,可以是同一个文件或被index.html包含的另一个文件 
angular.module('myApp') 
.controller('SomeController', function($scope, $element, $attrs, $transclude) { 
// 控制器逻辑放在这里 
}); 
也可以直接在指令内部的定义为匿名函数,同样我们可以再这里注入任何服务($log,$timeout等等)

[html] view plain copy 在CODE上查看代码片派生到我的代码片
angular.module('myApp',[]) 
.directive('myDirective', function() { 
restrict: 'A', 
controller: 
function($scope, $element, $attrs, $transclude) { 
// 控制器逻辑放在这里 
} 
}); 

另外还有一些特殊的服务(参数)可以注入

(1)$scope,与指令元素相关联的作用域

(2)$element,当前指令对应的 元素

(3)$attrs,由当前元素的属性组成的对象

(4)$transclude,嵌入链接函数,实际被执行用来克隆元素和操作DOM的函数

注意: 除非是用来定义一些可复用的行为,一般不推荐在这使用。
         指令的控制器和link函数(后面会讲)可以进行互换。区别在于,控制器主要是用来提供可在指令间复用的行为但link链接函数只能在当前内部指令中定义行为,且无法再指令间复用。

<!DOCTYPE html> 
<html lang="zh" ng-app="myApp"> 
<head> 
 <meta charset="UTF-8"> 
 <title>AngularJS入门学习</title> 
 <script type="text/javascript" src="./1.5.3/angular.min.js"></script> 
</head> 
 <hello mycolor ="red">我是林炳文~~~</hello> 
</body> 
<script type="text/javascript"> 
var app = angular.module('myApp', []); 
app.directive('hello', function() { 
 return { 
  restrict: 'EA', 
  transclude: true, //注意此处必须设置为true 
  controller: 
  function ($scope, $element,$attrs,$transclude,$log) { //在这里你可以注入你想注入的服务 
  $transclude(function (clone) { 
   var a = angular.element('<p>'); 
   a.css('color', $attrs.mycolor); 
   a.text(clone.text()); 
   $element.append(a); 
  }); 
  $log.info("hello everyone"); 
  } 
 }; 
 }); 
</script> 
</html> 

输出结果:


并且在控制台下输出hello everyone

让我们看看$transclude();在这里,它可以接收两个参数,第一个是$scope,作用域,第二个是带有参数clone的回调函数。而这个clone实际上就是嵌入的内容(经过jquery包装),可以在它上做很多DOM操作。

它还有最简单的用法就是

<script> 
 angular.module('myApp',[]).directive('mySite', function () { 
 return { 
  restrict: 'EA', 
  transclude: true, 
  controller: 
  function ($scope, $element,$attrs,$transclude,$log) { 
  var a = $transclude(); //$transclude()就是嵌入的内容 
  $element.append(a); 
  } 
 }; 
 }); 
 </script> 

注意:使用$transclude会生成一个新的作用域。
默认情况下,如果我们简单实用$transclude(),那么默认的其作用域就是$transclude生成的作用域

但是如果我们实用$transclude($scope,function(clone){}),那么作用域就是directive的作用域了

那么问题又来了。如果我们想实用父作用域呢

可以使用$scope.$parent

同理想要一个新的作用域也可以使用$scope.$parent.new();
10.controllerAs
这个选项的作用是可以设置你的控制器的别名

一般以前我们经常用这样方式来写代码:

angular.module("app",[]) 
 .controller("demoController",["$scope",function($scope){ 
 $scope.title = "angualr"; 
 }]) 
 
 <div ng-app="app" ng-controller="demoController"> 
 {{title}} 
</div> 

后来angularjs1.2给我们带来新语法糖,所以我们可以这样写

angular.module("app",[]) 
 .controller("demoController",[function(){ 
 this.title = "angualr"; 
 }]) 
 
 <div ng-app="app" ng-controller="demoController as demo"> 
 {{demo.title}} 
 </div> 

同样的我们也可以再指令里面也这样写

<script> 
 angular.module('myApp',[]).directive('mySite', function () { 
 return { 
  restrict: 'EA', 
  transclude: true, 
  controller:'someController', 
  controllerAs:'mainController' 
  //..其他配置 
 }; 
 }); 
 </script> 

11.require(字符串或者数组)
字符串代表另一个指令的名字,它将会作为link函数的第四个参数。具体用法我们可以举个例子说明。假设现在我们要编写两个指令,两个指令中的link链接函数中(link函数后面会讲)存在有很多重合的方法,这时候我们就可以将这些重复的方法写在第三个指令的controller中(上面也讲到controller经常用来提供指令间的复用行为)然后在这两个指令中,require这个拥有controller字段的的指令(第三个指令),

最后通过link链接函数的第四个参数就可以引用这些重合的方法了。

<!doctype html> 
<html ng-app="myApp"> 
<head> 
 <script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script> 
</head> 
<body> 
 
  
 <outer-directive> 
 <inner-directive></inner-directive> 
 <inner-directive2></inner-directive2> 
 </outer-directive> 
 <script> 
 var app = angular.module('myApp', []); 
 app.directive('outerDirective', function() { 
  return { 
  scope: {}, 
  restrict: 'AE', 
  controller: function($scope) { 
   this.say = function(someDirective) { 
   console.log('Got:' + someDirective.message); 
   }; 
  } 
  }; 
 }); 
 app.directive('innerDirective', function() { 
  return { 
  scope: {}, 
  restrict: 'AE', 
  require: '^outerDirective', 
  link: function(scope, elem, attrs, controllerInstance) { 
   scope.message = "Hi,leifeng"; 
   controllerInstance.say(scope); 
  } 
  }; 
 }); 
 app.directive('innerDirective2', function() { 
  return { 
  scope: {}, 
  restrict: 'AE', 
  require: '^outerDirective', 
  link: function(scope, elem, attrs, controllerInstance) { 
   scope.message = "Hi,shushu"; 
   controllerInstance.say(scope); 
  } 
  }; 
 }); 
 
 
 </script> 
 
</body> 
</html> 

上記の例の命令 innerDirective と innerDirective2 は、命令 externalDirective

のコントローラーで定義されたメソッドを再利用します。

では、命令内のコントローラーが異なる命令間の通信に使用されることもさらに説明されています。

さらに、require パラメーター値に次のプレフィックスのいずれかを追加できます。これにより、検索コントローラーの動作が変更されます。

(1) プレフィックスがない場合、命令はそれ自身が提供するコントローラー内を検索し、コントローラーが見つからない場合はエラーがスローされます。

(2)?現在の命令で必要なコントローラーが見つからない場合、リンク接続関数

の 4 番目のパラメーターに null が渡されます。

(3)^現在のディレクティブに必要なコントローラーが見つからない場合は、親要素のコントローラーが検索されます

(4)?^ 組み合わせ

12.Anguar命令コンパイル処理
まず angularjs ライブラリをロードし、ng-app ディレクティブを見つけてアプリケーションの境界を見つけます。

ng-app で定義されたスコープに従って、コンパイルのために $compile サービスを呼び出します。Angularjs は HTML ドキュメント全体を走査し、js の命令の定義に従ってページで宣言された各命令を、その優先順位に従って処理します。 ) を配置し、命令内の設定パラメータ (テンプレート、配置、トランスクルードなど) に従って DOM を変換し、各命令のコンパイル関数を順番に実行し始めます (命令にコンパイル関数が定義されている場合)。テンプレート自体を変換する

注: ここでのコンパイル機能はコマンドで設定されており、上記の $compile サービスとは異なります。各コンパイル関数が実行されると、リンク関数が返され、すべてのリンク関数が 1 つの大きなリンク関数に合成されます

次に、この大きなリンク関数は、DOM にリスナーを登録してスコープ内のデータを動的に変更するか、$watchs を使用してスコープ内の変数をリッスンして DOM を変更することによって、主にデータ バインディングのために実行されます。したがって、双方向バインディングなどを作成します。コンパイル関数が指示で設定されていない場合、設定したリンク関数が実行されます。これは、上記のコンパイルが返された後にすべてのリンク関数によって合成される大きなリンク関数とほぼ同じです。

つまり、コマンド内のコンパイル オプションとリンク オプションは相互に排他的です。これら 2 つのオプションが同時に設定されている場合、コンパイルによって返される関数はリンク関数とみなされ、リンク オプション自体は無視されます。 🎜>

13. コンパイル関数 コンパイル関数

関数のコンパイル(tElement, tAttrs, transclude) { ... }

コンパイルされた関数は、テンプレート DOM を変更する必要がある状況を処理するために使用されます。ほとんどの命令ではテンプレートを変更する必要がないため、この関数は一般的には使用されません。使用する必要がある例には、テンプレートの変更が必要な ngTrepeat や、コンテンツの非同期読み込みが必要な ngView などがあります。コンパイルされた関数は次のパラメータを受け入れます。


tElement - テンプレート要素 - 命令が配置される要素。この要素とその子に対して変換などの操作を安全に実行できます。

tAttrs - テンプレート属性 - この要素のすべてのディレクティブによって宣言された属性 これらの属性は、コンパイルされた関数間で共有されます。

transclude - 埋め込みリンク関数 function(scope, cloneLinkingFn)。
注: コンパイルされた関数では、DOM 変換以外の操作を実行しないでください。 さらに重要なのは、DOM リスニング イベントの登録は、コンパイルされた関数ではなく、リンク関数で行う必要があることです。
コンパイルされた関数はオブジェクトまたは関数を返すことができます。
コンパイルされた関数が存在しない場合に、構成オブジェクトのリンク属性を使用して登録されたリンク関数と同等の関数を返します。
オブジェクトを返す - pre または post 属性を介して登録された関数を持つオブジェクトを返します。以下のプリリンク機能とポストいいね機能の説明を参照してください。

14. リンク機能 関数リンク(スコープ、iElement、iAttrs、コントローラー) { ... }

リンク関数は、DOM イベントの登録と DOM の更新を担当します。これはテンプレートが複製された後に実行され、ディレクティブ ロジックのほとんどがここに書き込まれます。

スコープ - ディレクティブがリッスンする必要があるスコープ。
iElement - インスタンス要素 - 命令が配置される要素。 postLink 関数で要素の子を操作する場合のみ安全です。これは、要素の子がすべてリンクされているためです。
iAttrs - インスタンス属性 - 現在の要素で宣言されたすべての属性の標準化されたリスト。これらの属性はすべてのリンク関数間で共有されます。
controller - コントローラー インスタンス。現在の命令が require を通じて要求する direct2 内のコントローラーです。たとえば、direct2 命令でcontroller:function(){this.addStrength = function(){}}とすると、現在の命令のリンク関数でcontroller.addStrengthを通じて呼び出すことができます。
プレリンク関数は、子要素がリンクされる前に実行されます。リンク関数がリンクする正しい要素を見つけられない場合、DOM を変換するために使用することはできません。
ポストリンク関数は、すべての要素がリンクされた後に実行されます。


手順:

    compile選項本身並不會被頻繁使用,但是link函數則會被經常使用。本質上,當我們設定了link選項,實際上是建立了一個postLink() 連結函數,以便compile() 函數可以定義連結函數。通常情況下,如果設定了compile函數,說明我們希望在指令和即時資料放到DOM之前進行DOM操作,在這個函數中進行諸如添加和刪除節點等DOM操作是安全的。 compile和link選項是互斥的。如果同時設定了這兩個選項,那麼會把compile所傳回的函數當作連結函數,而link選項本身則會被忽略。譯函數負責將模板DOM轉換。連結函數負責將作用域和DOM進行連結。 在作用域同DOM連結之前可以手動操作DOM。在實踐中,編寫自訂指令時這種操作是非常罕見的,但有幾個內建指令提供了這樣的功能。 連結函數是可選的。如果定義了編譯函數,它會傳回連結函數,因此當兩個函數都定義時,編譯函數會重載連結函數。如果我們的指令很簡單,並且不需要額外的設置,可以從工廠函數(回呼函數)返回一個函數來代替物件。如果這樣做了,這個函數就是連結函數。

本文轉載http://blog.csdn.net/evankaka

以上就是AngularJs:Directive指令用法的全部內容,希望對大家的學習有所幫助。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。