搜尋
首頁web前端js教程深入淺析Angular中Directive的用法

深入淺析Angular中Directive的用法

Apr 13, 2021 am 10:45 AM
angulardirective

這篇文章給大家詳細介紹一下Angular Directive,了解它的用法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

深入淺析Angular中Directive的用法

Angular Directive 學習

學習目的:為了更好的了解 ng directive 的使用方法。

Directive可能是AngularJS中比較複雜的一個東西了。一般我們將其理解成指令。 AngularJS自帶了不少預設的指令,例如ng-app,ng-controller這些。可以發現個特點,AngularJS自帶的指令都是由ng-打頭的。

那麼,Directive究竟是個怎麼樣的東西呢?我個人的理解是這樣的:將一段html、js封裝在一起,形成一個可重複使用的獨立個體,具體特定的功能。下面我們來詳細解讀Directive的一般性用法。

AnguarJS directive的常用定義格式以及參數說明

看下面的程式碼:

var myDirective = angular.module('directives', []);

myDirective.directive('directiveName', function($inject) {
    return {
        template: '<div></div>',
        replace: false,
        transclude: true,
        restrict: 'E',
        scope: {},
        controller: function($scope, $element) {

        },
        complie: function(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) {

                },
                post: function postLink(scope, iElement, iAttrs, controller) {

                }
            };
        },
        link: function(scope, iElement, iAttrs) {

        }
    };
});
  • 這裡直接return了一個object,物件中包含比較多的屬性,這些屬性都是自訂directive的定義。詳細的含義,下面會繼續說明。
  • return物件參數說明
return {
    name: '',
    priority: 0,
    terminal: true,
    scope: {},
    controller: fn,
    require: fn,
    restrict: '',
    template: '',
    templateUrl: '',
    replace: '',
    transclude: true,
    compile: fn,
    link: fn
}

相關教學推薦:《angular教學

如上所示,return的物件中會有很多的屬性,這行屬性都是用來定義directive的。

下面我們來一個個的說明他們的作用。

  • name

    • 表示目前scope的名稱,一般聲明時使用預設值,不用手動設定此屬性。
  • priority

    • #優先權。當有多個directive定義在同一個DOM元素上時,有時需要明確他們的執行順序。這個屬性用於在directive的compile function呼叫之前進行排序。如果優先順序相同,則執行順序是不確定的(根據經驗,優先順序高的先執行,相同優先權時按照先綁定後執行)。
  • teminal

    • #最後一組。如果設定為true,表示目前的priority將會成為最後一組執行的directive,也就是比此directive的priority更低的directive將不會執行。同優先級依然會執行,但是順序不確定。
  • scope

    • #true
      • 將為這個directive建立一個新的scope。如果在同一個元素中有多個directive需要新的scope的話,它還是只會建立一個scope。新的作用域規則不適用於根模版,因為根模版往往會獲得一個新的scope。
    • {}
      • 將創建一個新的、獨立的scope,此scope與一般的scope的區別在於它不是透過原型繼承於父scope的。這對於建立可重複使用的元件是很有幫助的,可以有效的防止讀取或修改父級scope的資料。這個獨立的scope會創建一個擁有一組來自父scope的本地scope屬性hash集合。這些本地scope屬性對於模版創建值的別名很有幫助。本地的定義是對其來源的一組本地scope property的hash映射。
  • controller

    • controller建構子。 controller會在pre-linking步驟之前進行初始化,並允許其他directive透過指定名稱的require進行共用。這將允許directive之間相互溝通,增強相互之間的行為。 controller預設注入了以下本地物件:
      • $scope 與目前元素結合的scope
      • $element 目前的元素
      • $attrs 目前元素的屬性物件
      • $transclude 一個預先綁定到目前scope的轉置linking function
  • require

    • #請求另外的controller,傳入目前directive的linking function。 require需要傳入一個directive controller的名稱。如果找不到這個名稱對應的controller,那麼將會拋出一個error。名稱可以加入以下前綴:
      • ? 不要拋出例外。這將使得這個依賴變成一個可選項
      • ^ 允許查找父元素的controller
  • restrict

    • EACM的子集的字串,它限制了directive為指定的宣告方式。如果省略的話,directive將只允許透過屬性宣告
        ##E 元素名稱:
      • A 屬性名稱:
      • C class名稱:
      • ##M 註解:
  • template

    #如果replace為true,則將模版內容取代目前的html元素,並將原來元素的屬性、class一並轉移;如果replace為false,則將模版元素當作當前元素的子元素處理。
  • templateUrl

    <ul><li>与template基本一致,但模版通过指定的url进行加载。因为模版加载是异步的,所有compilation、linking都会暂停,等待加载完毕后再执行。</li></ul>

  • replace

    • 如果设置为true,那么模版将会替换当前元素,而不是作为子元素添加到当前元素中。(为true时,模版必须有一个根节点)
  • transclude

    • 编译元素的内容,使它能够被directive使用。需要在模版中配合ngTransclude使用。transclusion的有点是linking function能够得到一个预先与当前scope绑定的transclusion function。一般地,建立一个widget,创建独立scope,transclusion不是子级的,而是独立scope的兄弟级。这将使得widget拥有私有的状态,transclusion会被绑定到父级scope中。(上面那段话没看懂。但实际实验中,如果通过调用myDirective,而transclude设置为true或者字符串且template中包含的时候,将会将的编译结果插入到sometag的内容中。如果any的内容没有被标签包裹,那么结果sometag中将会多了一个span。如果本来有其他东西包裹的话,将维持原状。但如果transclude设置为’element’的话,any的整体内容会出现在sometag中,且被p包裹)
      • true/false 转换这个directive的内容。(这个感觉上,是直接将内容编译后搬入指定地方)
      • ‘element’ 转换整个元素,包括其他优先级较低的directive。(像将整体内容编译后,当作一个整体(外面再包裹p),插入到指定地方)
  • compile

    • 这里是compile function,将在下面实例详细说明
  • link

    • 这里是link function ,将在下面实例详细讲解。这个属性仅仅是在compile属性没有定义的情况下使用。

关于scope

这里关于directive的scope为一个object时,有更多的内容非常有必要说明一下。看下面的代码:

scope: {
    name: '=',
    age: '=',
    sex: '@',
    say: '&'
}

这个scope中关于各种属性的配置出现了一些奇怪的前缀符号,有=,@,&,那么这些符号具体的含义是什么呢?再看下面的代码:

  • html
<div my-directive name="myName" age="myAge" sex="male" say="say()"></div>复制代码
  • javascript
function Controller($scope) {
    $scope.name = 'Pajjket';
    $scope.age = 99;
    $scope.sex = '我是男的';
    $scope.say = function() {
        alert('Hello,我是弹出消息');
    };
}
可以看出,几种修饰前缀符的大概含义:
  • =: 指令中的属性取值为Controller中对应$scope上属性的取值
  • @: 指令中的取值为html中的字面量/直接量
  • &: 指令中的取值为Controller中对应$scope上的属性,但是这个属性必须为一个函数回调 下面是更加官方的解释:
  • =或者=expression/attr

在本地scope属性与parent scope属性之间设置双向的绑定。如果没有指定attr名称,那么本地名称将与属性名称一致。

  • 例如: 中,widget定义的scope为:{localModel: '=myAttr'},那么widget scope property中的localName将会映射父scope的parentModel。如果parentModel发生任何改变,localModel也会发生改变,反之亦然。即双向绑定。

  • @或者@attr 建立一个local scope property到DOM属性的绑定。因为属性值总是String类型,所以这个值总返回一个字符串。如果没有通过@attr指定属性名称,那么本地名称将与DOM属性的名称一致。 例如: ,widget的scope定义为:{localName: '@myAttr'}。那么,widget scope property的localName会映射出"hello "转换后的真实值。当name属性值发生改变后,widget scope的localName属性也会相应的改变(仅仅是单向,与上面的=不同)。那么属性是在父scope读取的(不是从组件的scope读取的)

  • &或者&attr 提供一个在父scope上下文中执行一个表达式的途径。如果没有指定attr的名称,那么local name将与属性名一致。

    • 例如:

<widget my-attr="count = count + value"></widget>,widget的scope定义为:{localFn:’increment()’},那么isolate scope property localFn会指向一个包裹着increment()表达式的function。 一般来说,我们希望通过一个表达式,将数据从isolate scope传到parent scope中。这可以通过传送一个本地变量键值的映射到表达式的wrapper函数中来完成。例如,如果表达式是increment(amount),那么我们可以通过localFn({amount:22})的方式调用localFn以指定amount的值。

directive 实例讲解

下面的示例都围绕着上面所作的参数说明而展开的。

  • directive声明实例
// 自定义directive
var myDirective = angular.modeule(&amp;#39;directives&amp;#39;, []);

myDirective.directive(&amp;#39;myTest&amp;#39;, function() {
    return {
        restrict: &amp;#39;EMAC&amp;#39;,
        require: &amp;#39;^ngModel&amp;#39;,
        scope: {
            ngModel: &amp;#39;=&amp;#39;
        },
        template: &amp;#39;&lt;div&gt;&lt;h4&gt;Weather for {{ngModel}}&lt;/h4&lt;/div&gt;&amp;#39;
    };
});

// 定义controller
var myControllers = angular.module(&amp;#39;controllers&amp;#39;, []);
myControllers.controller(&amp;#39;testController&amp;#39;, [
    &amp;#39;$scope&amp;#39;,
    function($scope) {
        $scope.name = &amp;#39;this is directive1&amp;#39;;
    }
]);


var app = angular.module(&amp;#39;testApp&amp;#39;, [
    &amp;#39;directives&amp;#39;,
    &amp;#39;controllers&amp;#39;
]);

&lt;body ng-app=&quot;testApp&quot;&gt;
    &lt;div ng-controller=&quot;testController&quot;&gt;
        &lt;input type=&quot;text&quot; ng-model=&quot;city&quot; placeholder=&quot;Enter a city&quot; /&gt;
        &lt;my-test ng-model=&quot;city&quot; &gt;&lt;/my-test&gt;
        &lt;span my-test=&quot;exp&quot; ng-model=&quot;city&quot;&gt;&lt;/span&gt;
        &lt;span ng-model=&quot;city&quot;&gt;&lt;/span&gt;
    &lt;/div&gt;
&lt;/body&gt;

template与templateUrl的区别和联系

templateUrl其实根template功能是一样的,只不过templateUrl加载一个html文件,上例中,我们也能发现问题,template后面根的是html的标签,如果标签很多呢,那就比较不爽了。可以将上例中的,template改一下。

myDirective.directive(&amp;#39;myTest&amp;#39;, function() {
    return {
        restrict: &amp;#39;EMAC&amp;#39;,
        require: &amp;#39;^ngModel&amp;#39;,
        scope: {
            ngModel: &amp;#39;=&amp;#39;
        },
        templateUrl:&amp;#39;../partials/tem1.html&amp;#39;   //tem1.html中的内容就是上例中template的内容。
    }
});

scope重定义

//directives.js中定义myAttr
myDirectives.directive(&amp;#39;myAttr&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        scope: {
            customerInfo: &amp;#39;=info&amp;#39;
        },
        template: &amp;#39;Name: {{customerInfo.name}} Address: {{customerInfo.address}}&lt;br&gt;&amp;#39; +
                  &amp;#39;Name: {{vojta.name}} Address: {{vojta.address}}&amp;#39;
    };
});

//controller.js中定义attrtest
myControllers.controller(&amp;#39;attrtest&amp;#39;,[&amp;#39;$scope&amp;#39;,
    function($scope) {
        $scope.naomi = {
            name: &amp;#39;Naomi&amp;#39;,
            address: &amp;#39;1600 Amphitheatre&amp;#39;
        };
        $scope.vojta = {
            name: &amp;#39;Vojta&amp;#39;,
            address: &amp;#39;3456 Somewhere Else&amp;#39;
        };
    }
]);

// html中
&lt;body ng-app=&quot;testApp&quot;&gt;
    &lt;div ng-controller=&quot;attrtest&quot;&gt;
        &lt;my-attr info=&quot;naomi&quot;&gt;&lt;/my-attr&gt;
    &lt;/div&gt;
&lt;/body&gt;

其运行结果如下:

Name: Naomi Address: 1600 Amphitheatre      //有值,因为customerInfo定义过的
Name: Address:                              //没值 ,因为scope重定义后,vojta是没有定义的

我们将上面的directive简单的改一下,

myDirectives.directive(&amp;#39;myAttr&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        template: &amp;#39;Name: {{customerInfo.name}} Address: {{customerInfo.address}}&lt;br&gt;&amp;#39; +
                  &amp;#39;Name: {{vojta.name}} Address: {{vojta.address}}&amp;#39;
    };
});
  • 运行结果如下:
Name: Address:
Name: Vojta Address: 3456 Somewhere Else

因为此时的directive没有定义独立的scope,customerInfo是undefined,所以结果正好与上面相反。

transclude的使用

  • transclude的用法,有点像jquery里面的$().html()功能
myDirective.directive(&amp;#39;myEvent&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        transclude: true,
        scope: {
            &amp;#39;close&amp;#39;: &amp;#39;$onClick&amp;#39;      //根html中的on-click=&quot;hideDialog()&quot;有关联关系
        },
        templateUrl: &amp;#39;../partials/event_part.html&amp;#39;
    };
});

myController.controller(&amp;#39;eventTest&amp;#39;, [
    &amp;#39;$scope&amp;#39;,
    &amp;#39;$timeout&amp;#39;,
    function($scope, $timeout) {
        $scope.name = &amp;#39;Tobias&amp;#39;;
        $scope.hideDialog = function() {
            $scope.dialogIsHidden = true;
            $timeout(function() {
                $scope.dialogIsHidden = false;
            }, 2000);
        };
    }
]);
&lt;body ng-app=&quot;phonecatApp&quot;&gt;
    &lt;div ng-controller=&quot;eventtest&quot;&gt;
        &lt;my-event ng-hide=&quot;dialogIsHidden&quot; on-click=&quot;hideDialog()&quot;&gt;
            Check out the contents, {{name}}!
        &lt;/my-event&gt;
    &lt;/div&gt;
&lt;/body&gt;

&lt;!--event_part.html --&gt;
&lt;div&gt;
    &lt;a href ng-click=&quot;close()&quot;&gt;×&lt;/a&gt;
    &lt;div ng-transclude&gt;&lt;/div&gt;
&lt;/div&gt;
  • 说明:这段html最终的结构应该如下所示:
&lt;body ng-app=&quot;phonecatApp&quot;&gt;
    &lt;div ng-controller=&quot;eventtest&quot;&gt;
        &lt;div ng-hide=&quot;dialogIsHidden&quot; on-click=&quot;hideDialog()&quot;&gt;
            &lt;span&gt;Check out the contents, {{name}}!&lt;/span&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
  • 将原来的html元素中的元素Check out the contents, !插入到模版的中,还会另外附加一个标签。controllerlinkcompile之间的关系
myDirective.directive(&amp;#39;exampleDirective&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        template: &amp;#39;&lt;p&gt;Hello {{number}}!&lt;/p&gt;&amp;#39;,
        controller: function($scope, $element){
            $scope.number = $scope.number + &quot;22222 &quot;;
        },
        link: function(scope, el, attr) {
            scope.number = scope.number + &quot;33333 &quot;;
        },
        compile: function(element, attributes) {
            return {
                pre: function preLink(scope, element, attributes) {
                    scope.number = scope.number + &quot;44444 &quot;;
                },
                post: function postLink(scope, element, attributes) {
                    scope.number = scope.number + &quot;55555 &quot;;
                }
            };
        }
    }
});

//controller.js添加
myController.controller(&amp;#39;directive2&amp;#39;,[
    &amp;#39;$scope&amp;#39;,
    function($scope) {
        $scope.number = &amp;#39;1111 &amp;#39;;
    }
]);

//html
&lt;body ng-app=&quot;testApp&quot;&gt;
    &lt;div ng-controller=&quot;directive2&quot;&gt;
        &lt;example-directive&gt;&lt;/example-directive&gt;
    &lt;/div&gt;
&lt;/body&gt;
  • 上面小例子的运行结果如下:
Hello 1111 22222 44444 5555 !

由结果可以看出来,controller先运行,compile后运行,link不运行。 我们现在将compile属性注释掉后,得到的运行结果如下:Hello 1111 22222 33333 !

由结果可以看出来,controller先运行,link后运行,link和compile不兼容。一般地,compile比link的优先级要高。

更多编程相关知识,请访问:编程入门!!

以上是深入淺析Angular中Directive的用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金社区。如有侵權,請聯絡admin@php.cn刪除
JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器