AngularJs ディレクティブを理解する_AngularJS
對於指令,可以把它簡單的理解成在特定DOM元素上運行的函數,指令可以擴展這個元素的功能。
首先來看個完整的參數範例再來詳細的介紹各個參數的作用及用法:
angular.module('myApp', []) .directive('myDirective', function() { return { restrict: String, priority: Number, terminal: Boolean, template: String or Template Function: function(tElement, tAttrs) {...}, templateUrl: String, replace: Boolean or String, scope: Boolean or Object, transclude: Boolean, controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }, controllerAs: String, require: String, link: function(scope, iElement, iAttrs) { ... }, compile: // 返回一个对象或连接函数,如下所示: function(tElement, tAttrs, transclude) { return { pre: function(scope, iElement, iAttrs, controller) { ... }, post: function(scope, iElement, iAttrs, controller) { ... } } return function postLink(...) { ... } } }; });
1、restrict[string]
restrict是一個可選的參數。用於指定該指令在DOM中以何種形式被聲明。預設值是A,即以屬性的形式來進行宣告。
可選值如下:
E(元素)
A(屬性,預設值)
C(類別名稱)
M(註)
<--directive:my-directive expression-->
一般考慮到瀏覽器的兼容性,強烈建議使用預設的屬性就可以即以屬性的形式來進行聲明。最後一種方式建議再不要求逼格指數的時候千萬不要用。
Code:
angular.module('app',[]) .directive('myDirective', function () { return { restrict: 'E', template: '<a href="http://www.baidu.com">百度</a>' }; }) HtmlCode: <my-directive></my-directive>
效果:
2、priority[int]
大多數指令會忽略這個參數,使用預設值0,但也有些場景設定高優先權是非常重要甚至是必須的。例如,ngRepeat將這個參數設為1000,這樣就可以保證在同一元素上,它總是在其他指令之前被呼叫。
3、terminal[bool]
這個參數用來停止執行目前元素上比本指令優先權低的指令。但同當前指令優先權相同的指令還是會被執行。
例如:ngIf的優先權略高於ngView(它們操控的實際就是terminal參數),如果ngIf的表達式值為true,ngView就可以正常執行,但如果ngIf表達式的值為false,由於ngView的優先級較低就不會被執行。
4、template[string or function]
template參數是可選的,必須被設定為以下兩種形式之一:
- 一段HTML文字;
- 一個可以接受兩個參數的函數,參數為tElement和tAttrs,並傳回一個代表模板的字串。 tElement和tAttrs中的t代表template,是相對於instance的。
首先示範下第二種用法:
angular.module('app',[]) .directive('myDirective', function () { return { restrict: 'EAC', template: function (elem, attr) { return "<a href='" + attr.value + "'>" + attr.text + "</a>"; } }; })
HtmlCode:(效果同上,不做示範了)
<my-directive value="http://www.baidu.com" text="百度"></my-directive> <div my-directive value="http://www.baidu.com" text="百度"></div>
5、templateUrl[string or function]
templateUrl是可選的參數,可以是以下類型:
- 一個代表外部HTML檔案路徑的字串;
- 一個可以接受兩個參數的函數,參數為tElement和tAttrs,並傳回一個外部HTML檔案路徑的字串。
無論哪種方式,模板的URL都會透過ng內建的安全層,特別是$getTrustedResourceUrl,這樣可以保護模板不會被不信任的來源載入。 預設情況下,呼叫指令時會在後台透過Ajax來請求HTML模板檔。載入大量的模板將嚴重拖慢一個客戶端應用的速度。為了避免延遲,可以在部署應用之前對HTML模板進行快取。
Code:
angular.module('app',[]) .directive('myDirective', function () { return { restrict: 'AEC', templateUrl: function (elem, attr) { return attr.value + ".html"; //当然这里我们可以直接指定路径,同时在模板中可以包含表达式 } }; })
6、replace[bool]
replace是一個可選參數,如果設定了這個參數,值必須為true,因為預設值為false。預設值表示範本會被當作子元素插入到呼叫此指令的元素內部,
例如上面的範例預設值情況下,產生的html程式碼如下:
<my-directive value="http://www.baidu.com" text="百度"><a href="http://www.baidu.com">百度</a></my-directive>
如果設定replace=true
<a href="http://www.baidu.com" value="http://www.baidu.com" text="百度">百度</a>
据我观察,这种效果只有设置restrict="E"的情况下,才会表现出实际效果。
介绍完基本的指令参数后,就要涉及到更重要的作用域参数了...
7、scope参数[bool or object]
scope参数是可选的,可以被设置为true或一个对象。默认值是false。
如果一个元素上有多个指令使用了隔离作用域,其中只有一个可以生效。只有指令模板中的根元素可以获得一个新的作用域。因此,对于这些对象来说scope默认被设置为true。内置指令ng-controller的作用,就是从父级作用域继承并创建一个新的子作用域。它会创建一个新的从父作用域继承而来的子作用域。这里的继承就不在赘述,和面向对象中的继承基本是一直的。
首先我们来分析一段代码:
<div ng-app="app" ng-init="name= '祖父'"> <div ng-init="name='父亲'"> 第一代:{{ name }} <div ng-init="name= '儿子'" ng-controller="SomeController"> 第二代: {{ name }} <div ng-init="name='孙子'"> 第三代: {{ name }} </div> </div> </div> </div>
我们发现第一代,我们初始化name为父亲,但是第二代和第三代其实是一个作用域,那么他们的name其实是一个对象,因此出现的效果如下:
第一代:父亲
第二代: 孙子
第三代: 孙子
我们在修改一下代码,把第三代隔离开来再看看效果:
<div ng-app="app"ng-init="name= '祖父'"> <div ng-init="name='父亲'"> 第一代:{{ name }} <div ng-init="name= '儿子'" ng-controller="SomeController"> 第二代: {{ name }} <div ng-init="name='孙子'" ng-controller="SecondController"> 第三代: {{ name }} </div> </div> </div> </div>
JsCode:
angular.module('app', []) .controller('SomeController',function($scope) { }) .controller('SecondController', function ($scope) { })
效果如下:
第一代:父亲
第二代: 儿子
第三代: 孙子
在修改下代码来看看继承:
<div ng-app="app"ng-init="name= '祖父的吻'"> <div> 第一代:{{ name }} <div ng-controller="SomeController"> 第二代: {{ name }} <div ng-controller="SecondController"> 第三代: {{ name }} </div> </div> </div> </div>
效果如下:
第一代:祖父的吻
第二代: 祖父的吻
第三代: 祖父的吻
如果要创建一个能够从外部原型继承作用域的指令,将scope属性设置为true,简单来说就是可继承的隔离,即不能反向影响父作用域。
再来看个例子:
angular.module('myApp', []) .controller('MainController', function ($scope) { }) .directive('myDirective', function () { return { restrict: 'A', scope:false,//切换为{},true测试 priority: 100, template: '<div>内部:{{ myProperty }}<input ng-model="myProperty"/></div>' }; });
Html代码:
<div ng-controller='MainController' ng-init="myProperty='Hello World!'"> 外部: {{ myProperty}} <input ng-model="myProperty" /> <div my-directive></div> </div>
当我们改变scope的值我们会发现
false:继承但不隔离
true:继承并隔离
{}:隔离且不继承
8、transclude
transclude是一个可选的参数。默认值是false。嵌入通常用来创建可复用的组件,典型的例子是模态对话框或导航栏。我们可以将整个模板,包括其中的指令通过嵌入全部传入一个指令中。指令的内部可以访问外部指令的作用域,并且模板也可以访问外部的作用域对象。为了将作用域传递进去,scope参数的值必须通过{}或true设置成隔离作用域。如果没有设置scope参数,那么指令内部的作用域将被设置为传入模板的作用域。
只有当你希望创建一个可以包含任意内容的指令时,才使用transclude: true。
我们来看两个例子-导航栏:
<div side-box title="TagCloud"> <div class="tagcloud"> <a href="">Graphics</a> <a href="">ng</a> <a href="">D3</a> <a href="">Front-end</a> <a href="">Startup</a> </div> </div>
JsCode:
angular.module('myApp', []) .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>' }; });
这段代码告诉ng编译器,将它从DOM元素中获取的内容放到它发现ng-transclude指令的地方。
再来你看个官网的例子:
angular.module('docsIsoFnBindExample', []) .controller('Controller', ['$scope', '$timeout', function($scope, $timeout) { $scope.name = 'Tobias'; $scope.hideDialog = function () { $scope.dialogIsHidden = true; $timeout(function () { $scope.dialogIsHidden = false; }, 2000); }; }]) .directive('myDialog', function() { return { restrict: 'E', transclude: true, scope: { 'close': '&onClose' }, templateUrl: 'my-dialog-close.html' }; });
my-dialog-close.html
<div class="alert"> <a href class="close" ng-click="close()">×</a> <div ng-transclude></div> </div>
index.html
<div ng-controller="Controller"> <my-dialog ng-hide="dialogIsHidden" on-close="hideDialog()"> Check out the contents, {{name}}! </my-dialog> </div>
如果指令使用了transclude参数,那么在控制器无法正常监听数据模型的变化了。建议在链接函数里使用$watch服务。
9、controller[string or function]
controller参数可以是一个字符串或一个函数。当设置为字符串时,会以字符串的值为名字,来查找注册在应用中的控制器的构造函数.
angular.module('myApp', []) .directive('myDirective', function() { restrict: 'A', controller: 'SomeController' })
可以在指令内部通过匿名构造函数的方式来定义一个内联的控制器
angular.module('myApp',[]) .directive('myDirective', function() { restrict: 'A', controller: function($scope, $element, $attrs, $transclude) { // 控制器逻辑放在这里 } });
我们可以将任意可以被注入的ng服务注入到控制器中,便可以在指令中使用它了。控制器中也有一些特殊的服务可以被注入到指令当中。这些服务有:
1. $scope
与指令元素相关联的当前作用域。
2. $element
当前指令对应的元素。
3. $attrs
由当前元素的属性组成的对象。
<div id="aDiv"class="box"></div> 具有如下的属性对象: { id: "aDiv", class: "box" }
4. $transclude
嵌入链接函数会与对应的嵌入作用域进行预绑定。transclude链接函数是实际被执行用来克隆元素和操作DOM的函数。
angular.module('myApp',[]) .directive('myLink', function () { return { restrict: 'EA', transclude: true, controller: function ($scope, $element,$attrs,$transclude) { $transclude(function (clone) { var a = angular.element('<a>'); a.attr('href', $attrs.value); a.text(clone.text()); $element.append(a); }); } }; });
html
<my-link value="http://www.baidu.com">百度</my-link> <div my-link value="http://www.google.com">谷歌</div>
仅在compile参数中使用transcludeFn是推荐的做法。link函数可以将指令互相隔离开来,而controller则定义可复用的行为。如果我们希望将当前指令的API暴露给其他指令使用,可以使用controller参数,否则可以使用link来构造当前指令元素的功能性(即内部功能)。如果我们使用了scope.$watch()或者想要与DOM元素做实时的交互,使用链接会是更好的选择。使用了嵌入,控制器中的作用域所反映的作用域可能与我们所期望的不一样,这种情况下,$scope对象无法保证可以被正常更新。当想要同当前屏幕上的作用域交互时,可以使用传入到link函数中的scope参数。
10、controllerAs[string]
controllerAs参数用来设置控制器的别名,这样就可以在视图中引用控制器甚至无需注入$scope。
<div ng-controller="MainController as main"> <input type="text" ng-model="main.name" /> <span>{{ main.name }}</span> </div>
JsCode:
angular.module('myApp',[]) .controller('MainController', function () { this.name = "Halower"; });
控制器的别名使路由和指令具有创建匿名控制器的强大能力。这种能力可以将动态的对象创建成为控制器,并且这个对象是隔离的、易于测试。
11、 require[string or string[]]
require为字符串代表另外一个指令的名字。require会将控制器注入到其所指定的指令中,并作为当前指令的链接函数的第四个参数。字符串或数组元素的值是会在当前指令的作用域中使用的指令名称。在任何情况下,ng编译器在查找子控制器时都会参考当前指令的模板。
如果不使用^前缀,指令只会在自身的元素上查找控制器。指令定义只会查找定义在指令作当前用域中的ng-model=""
如果使用?前缀,在当前指令中没有找到所需要的控制器,会将null作为传给link函数的第四个参数。
如果添加了^前缀,指令会在上游的指令链中查找require参数所指定的控制器。
如果添加了?^ 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找
如果没有任何前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器(或具有指定名字的指令)就抛出一个错误
12、compile【object or function】
compile选项本身并不会被频繁使用,但是link函数则会被经常使用。本质上,当我们设置了link选项,实际上是创建了一个postLink() 链接函数,以便compile() 函数可以定义链接函数。通常情况下,如果设置了compile函数,说明我们希望在指令和实时数据被放到DOM中之前进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。
compile和link选项是互斥的。如果同时设置了这两个选项,那么会把compile所返回的函数当作链接函数,而link选项本身则会被忽略。
编译函数负责对模板DOM进行转换。链接函数负责将作用域和DOM进行链接。 在作用域同DOM链接之前可以手动操作DOM。在实践中,编写自定义指令时这种操作是非常罕见的,但有几个内置指令提供了这样的功能。
13、link
compile: function(tEle, tAttrs, transcludeFn) { //todo: return function(scope, ele, attrs) { // 链接函数 };
链接函数是可选的。如果定义了编译函数,它会返回链接函数,因此当两个函数都定义时,编译函数会重载链接函数。如果我们的指令很简单,并且不需要额外的设置,可以从工厂函数(回调函数)返回一个函数来代替对象。如果这样做了,这个函数就是链接函数。
14、ngModel
它提供更底层的API来处理控制器内的数据,这个API用来处理数据绑定、验证、 CSS更新等不实际操作DOM的事情,ngModel 控制器会随 ngModel 被一直注入到指令中,其中包含了一些方法。为了访问ngModelController必须使用require设置.
ngModelController常用的元素如下:
1).为了设置作用域中的视图值,需要调用 ngModel.$setViewValue() 函数。
$setViewValue() 方法适合于在自定义指令中监听自定义事件(比如使用具有回调函数的jQuery插件),我们会希望在回调时设置$viewValue并执行digest循环。
angular.module('myApp') .directive('myDirective', function() { return { require: '?ngModel', link: function(scope, ele, attrs, ngModel) { if (!ngModel) return; $(function() { ele.datepicker({ //回调函数 onSelect: function(date) { // 设置视图和调用 apply scope.$apply(function() { ngModel.$setViewValue(date); }); } }); }); } }; });
2).$render方法可以定义视图具体的渲染方式
3).属性(这里属性可以参考前一篇文章末尾进行学习)
以上就是关于AngularJs指令的全部内容,希望对大家的学习有所帮助。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Terrariaでコマンドを使用してアイテムを取得するにはどうすればよいですか? 1. Terraria でアイテムを与えるコマンドは何ですか? Terraria ゲームでは、アイテムにコマンドを与えることは非常に実用的な機能です。このコマンドにより、プレイヤーはモンスターと戦ったり、特定の場所にテレポートしたりすることなく、必要なアイテムを直接入手できます。これにより、時間が大幅に節約され、ゲームの効率が向上し、プレイヤーは世界の探索と構築により集中できるようになります。全体として、この機能によりゲーム体験がよりスムーズで楽しいものになります。 2. Terraria を使用してアイテム コマンドを与える方法 1. ゲームを開き、ゲーム インターフェイスに入ります。 2. キーボードの「Enter」キーを押してチャットウィンドウを開きます。 3. チャットウィンドウにコマンド形式「/give[プレイヤー名][アイテムID][アイテム数量]」を入力します。

この記事は、初心者が Vue.js3 をすぐに使い始めて、簡単なタブ切り替え効果を実現できるようにすることを目的としています。 Vue.js は、再利用可能なコンポーネントの構築、アプリケーションの状態の簡単な管理、ユーザー インターフェイスの操作の処理に使用できる人気の JavaScript フレームワークです。 Vue.js3 はフレームワークの最新バージョンであり、以前のバージョンと比較して大きな変更が加えられていますが、基本原理は変わっていません。この記事では、読者が Vue.js に慣れることを目的として、Vue.js の命令を使用してタブ切り替え効果を実装します。

Javascript は、コードの構成、コードのプログラミング パラダイム、およびオブジェクト指向理論の点で非常にユニークな言語です。しかし、JavaScript が 20 年間主流であったとはいえ、jQuery、Angularjs、さらには React などの人気のあるフレームワークを理解したい場合は、「Black Horse Cloud Classroom JavaScript Advanced Framework」を見てください。デザインビデオチュートリアル」。

今日の情報化時代において、ウェブサイトは人々が情報を入手し、コミュニケーションを図るための重要なツールとなっています。レスポンシブな Web サイトはさまざまなデバイスに適応し、ユーザーに高品質のエクスペリエンスを提供できます。これは、現代の Web サイト開発のホットスポットとなっています。この記事では、PHP と AngularJS を使用して応答性の高い Web サイトを構築し、高品質のユーザー エクスペリエンスを提供する方法を紹介します。 PHP の概要 PHP は、Web 開発に最適なオープンソースのサーバー側プログラミング言語です。 PHP には、学びやすさ、クロスプラットフォーム、豊富なツール ライブラリ、開発効率など、多くの利点があります。

モバイルデバイスは現代社会において人々の生活に欠かせないものとなっています。ゲームはまた、人々の余暇の主要な娯楽形式の 1 つとなっています。ゲームプレイを最適化し、ゲーム体験を向上させるための新しいツールやテクノロジーの開発に常に取り組んでいる人々がいます。独自の MC コマンドによる入力方法は、目を引く革新の 1 つです。そして、それがどのようにしてプレイヤーにより良いゲーム体験をもたらすことができるのか、この記事では、組み込みの MC コマンド入力方法の無限の可能性を掘り下げていきます。内蔵 MC コマンド入力メソッドの紹介 内蔵 MC コマンド入力メソッドは、MC コマンドの機能とインテリジェントな入力メソッドを組み合わせた革新的なツールです。これにより、モバイル デバイスに入力メソッドをインストールすることで、プレイヤーはゲーム内でさまざまなコマンドを簡単に使用できるようになります。コマンドを素早く入力してゲーム効率を向上

コンピュータが直接実行できる命令には、オペレーションコードとオペランドがあります。オペコードとは、コンピュータ プログラム内で操作を実行するために指定された命令またはフィールドの一部を指し、実際には命令シーケンス番号であり、どの命令を実行する必要があるかを CPU に伝えるために使用されます。

命令とはコンピュータの実行を制御する命令であり、オペレーションコードとアドレスコードで構成されます。通常、命令にはオペレーション コードとオペランド (アドレス コード) の 2 つの側面が含まれます。オペレーション コードは完了する演算を決定し、オペランドは演算に参加するデータとそのデータが配置されているユニットのアドレスを指します。

バブリング イベントを防ぐ命令には、stopPropagation()、cancelBubble 属性、event.stopPropagation()、event.cancelBubble 属性、event.stopImmediatePropagation() などが含まれます。詳細な紹介: 1. stopPropagation() は最も一般的に使用される命令の 1 つで、イベントの伝播を停止するために使用されます。イベントがトリガーされたときに、このメソッドを呼び出すと、イベントが継続できなくなる可能性があります。
