日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

AngularJS - 自定义指令

發布時間:2025/5/22 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AngularJS - 自定义指令 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這一篇從自定義指令出發,記錄了定義一個指令時影響指令行為的各種因素。

試著感受這些因素,讓自己更高效地編寫AngularJS應用。

Directive

先從定義一個簡單的指令開始。
定義一個指令本質上是在HTML中通過元素、屬性、類或注釋來添加功能。

AngularJS的內置指令都是以ng開頭,如果想自定義指令,建議自定義一個前綴代表自己的命名空間。

這里我們先使用my作為前綴:

var myApp = angular.module('myApp', []).directive('myDirective', function() {return {restrict: 'A',replace: true,template: '<p>Kavlez</p>'}; })

如此一來,我們可以這樣使用,注意命名是camel-case:

<my-directive /> <!-- <my-directive><p>Kavlez</p></my-directive> -->

directive()接受兩個參數

  • name:字符串,指令的名字
  • factory_function:函數,指令的行為

應用啟動時,以name作為該應用的標識注冊factory_function返回的對象。

在factory_function中,我們可以設置一些選項來改變指令的行為。

下面記錄一下定義指令時用到的選項

restrict (string)

該屬性用于定義指令以什么形式被使用,這是一個可選參數,本文開頭定義的指令用的也是A,其實該選項默認為A。

也就是元素(E)、屬性(A)、類(C)、注釋(M)

(ps:EMAC? EMACS? 挺好記哈)

比如上面定義的myDirective,可以以任何形式調用。

  • E(元素)
<my-directive></my-directive>
  • A(屬性,默認值)
<div my-directive="expression"></div>
  • C(類名)
<div class="my-directive:expression;"></div>
  • M(注釋)
<--directive:my-directive expression-->

priority (Number)

也就是優先級,默認為0。

在同一元素上聲明了多個指令時,根據優先級決定哪個先被調用。

如果priority相同,則按聲明順序調用。

另外,no-repeat是所有內置指令中優先級最高的。

terminal (Boolean)

終端? 而且還是Boolean?

被名字嚇到了,其實terminal的意思是是否停止當前元素上比該指令優先級低的指令
但是相同的優先級還是會執行。

比如,我們在my-directive的基礎上再加一個指令:

.directive('momDirective',function($rootScope){return{priority:3,terminal:true}; })

調用發現my-directive不會生效:

<div mom-directive my-directive="content" ></div>

?

template (String/Function)

至少得輸出點什么吧? 但template也是可選的。

String類型時,template可以是一段HTML。

Function類型時,template是一個接受兩個參數的函數,分別為:

  • tElement
  • tAttrs

函數返回一段字符串作為模板。

templateUrl (String/Function)

這個就和上面的template很像了,只不過這次是通過URL請求一個模板。
String類型時,templateURL自然是一個URL。
Function類型時返回一段字符串作為模板URL。

replace (Boolean/String)

默認值為false,以文章開頭定義的指令為例,假設我們這樣調用了指令

<my-directive></my-directive>

replace為true時,輸出:

<p>Kavlez</p>

replace為false時,輸出:

<my-directive><p>Kavlez</p></my-directive>

?

transclude (Boolean)

該選項默認為false,翻譯過來叫'嵌入',感覺還是有些生澀。

template和scope已經可以做很多事情了,但有一點不足。

比如在原有元素的基礎上添加內容,transclude的例子如下:

<body ng-app="myApp"><textarea ng-model="content"></textarea><div my-directive title="Kavlez"><hr>{{content}}</div> </body> <script type="text/javascript"> var myApp = angular.module('myApp', []) .directive('myDirective', function() {return {restrict: 'EA',scope: {title: '@',content: '='},transclude: true,template: '<h2 class="header">{{ title }}</h2>\<span class="content" ng-transclude></span>'}; }); </script>

發現div下的hr并沒有被移除,就是這樣的效果。

注意不要忘了在模板中聲明ng-transclude。

scope (Boolean/Object)

默認為false,true時會從父作用域繼承并創建一個自己的作用域。

而ng-controller的作用也是從父作用域繼承并創建一個新的作用域。

比如這樣,離開了自己的作用域就被打回原形了:

<div ng-init="content='from root'">{{content}}<div ng-controller="AncestorController">{{content}} <div ng-controller="ChildController">{{content}} </div>{{content}} </div>{{content}} </div>.controller('ChildController', function($scope) {$scope.content = 'from child'; }) .controller('AncestorController', function($scope) {$scope.content = 'from ancestor'; })

但不要誤解,指令嵌套并不一定會改變它的作用域。

既然true時會從父作用域繼承并創建一個自己的作用域,那么我們來試試改為false會是什么樣子:

<div ng-init="myProperty='test'">{{ myProperty }}<div my-directive ng-init="myProperty = 'by my-directive'">{{ myProperty }}</div>{{ myProperty }} </div>.directive('myDirective', function($rootScope) {return {scope:false}; })

顯然,結果是三行'by my-directive'。

非true即false? naive!

其實最麻煩的還是隔離作用域

我們稍微改動一下myDirective,改為輸出<p>{{內容}}</p>。

于是我試著這樣定義:

<body ng-app="myApp" ><p ng-controller="myController"><div my-directive="I have to leave." ></div>{{myDirective}}</p> </body> <script type="text/javascript"> var myApp = angular.module('myApp', []) .directive('myDirective', function($rootScope) {$rootScope.myDirective = 'from rootScope';return {priority:1000,restrict: 'A',replace: true,scope: {myDirective: '@',},template: '<p>{{myDirective}}</p>'}; }) .controller('myController',function($scope){$scope.myDirective = 'from controller'; }); </script>

這里需要注意的不是@,重點是隔離作用域

根據上面的例子輸出,template中的{{myDirective}}不會影響到其他作用域。

我們再試試這樣:

<input type="text" ng-model="content"> <p ng-controller="myController" > <div my-directive="{{content}}" ></div>{{content}} </p>

發現大家都在一起變,也就是說值是通過復制DOM屬性并傳遞到隔離作用域。

ng-model是個強大的指令,它將自己的隔離作用域和DOM作用域連在一起,這樣就是一個雙向數據綁定。

如何向指令的隔離作用域中傳遞數據,這里用了@。

或者也可以寫成@myDirective,也就是說換個名字什么的也可以,比如我用@myCafe什么的給myDirective賦值也是沒問題的,總之是和DOM屬性進行綁定。

另外,我們也可以用=進行雙向綁定,將本地作用域的屬性同父級作用域的屬性進行雙向綁定

比如下面的例子中,隔離作用域里的內容只能是'abc' :

<body ng-app="myApp" ng-init="content='abc'"><p ng-controller="myController" ><input type="text" ng-model="content"><div my-directive="content" ></div>{{content}}</p> </body> <script type="text/javascript"> var myApp = angular.module('myApp', []) .directive('myDirective', function($rootScope) {return {priority:1000,restrict: 'A',replace: true,scope: {myDirective: '=',},template: '<p>from myDirective:{{myDirective}}</p>'}; }) .controller('myController',function($scope){$scope.content = 'from controller'; }); </script>

在隔離作用域訪問指令外部的作用域的方法還有一種,就是&。

我們可以使用&與父級作用域的函數進行綁定,比如下面的例子:

<body ng-app="myApp"><div ng-controller="myController"><table border='1'><tr><td>From</td><td><input type="text" ng-model="from"/></td></tr><tr><td>To</td><td><input type="text" ng-model="to"/></td></tr><tr><td>Content</td><td><textarea cols="30" rows="10" ng-model="content"></textarea></td></tr><tr><td>Preview:</td><td><div scope-example to="to" on-send="sendMail(content)" from="from" /></td></tr></table></div> </div></body> <script type="text/javascript"> var myApp = angular.module('myApp', []) .controller('myController',function($scope){$scope.sendMail=function(content){console.log('content is:::'+content);} }) .directive('scopeExample',function(){return{restrict:'EA',scope: {to: '=', from: '=' ,send: '&onSend'},template:'<div>From:{{from}}<br>\To:{{to}}<br>\<button ng-click="send()">Send</button>\</div>'} }) </script>

controller (String/Function)

控制器也可以在指令里定義,比如:

.directive('myDirective', function() {restrict: 'A',controller: 'myController' }).controller('myController', function($scope, $element, $attrs,$transclude) {//... })

相同的效果,也可以這樣聲明:

directive('myDirective', function() {restrict: 'A',controller:function($scope, $element, $attrs, $transclude) {//...} }); ?

controllerAs (String)

可以從名字和類型看出,這個選項是用來設置控制器的別名的。

比如這樣:

directive('myDirective', function() {restrict: 'A',controller:function($scope, $element, $attrs, $transclude) {//...} });

compile (Object/Function)

雖說這個東西不是很常用吧,但卻是值得了解的選項。

compile和link,這兩個選項關系到AngularJS的生命周期。

先在這里簡單記錄一下我對生命周期的認識。

  • 應用啟動前,所有的指令以文本的形式存在。* 應用啟動后便開始進行compilelink,DOM開始變化,作用域與HTML進行綁定。* 在編譯階段,AngularJS會遍歷整個HTML并處理已聲明的指令。
  • 一個指令的模板中可能使用了另外一個指令,這個指令的模板中可能包含其他指令,如此層層下來便是一個模板樹。* 在DOM尚未進行數據綁定時對DOM進行操作開銷相對較小,這時像ng-repeat之類的指令對DOM進行操作則再合適不過了。
  • 我們可以用編譯函數訪問編譯后的DOM,在數據綁定之前用編譯函數對模板DOM進行轉換,編譯函數會返回模板函數。
    也就是說,設置compile函數的意義在于:在指令和實時數據被放到DOM中之前修改DOM
    此時完全可以毫無顧慮地操作DOM。
  • 接著我們便可以進入下一個階段,鏈接階段
  • 最后,模板函數傳遞給指令指定的鏈接函數,鏈接函數對作用域和DOM進行鏈接。

好了,接下來我們就試試compile:

<body ng-app="myApp"><my-directive ng-model="myName"></my-directive> </body> <script type="text/javascript"> var myApp = angular.module('myApp', []) .directive('myDirective', function($rootScope) {$rootScope.myName = 'Kavlez';return {restrict: 'EA',compile:function(tEle, tAttrs, transcludeFn) {var h2 = angular.element('<h2></h2>');h2.attr('type', tAttrs.type);h2.attr('ng-model', tAttrs.ngModel);h2.html("hello {{"+tAttrs.ngModel+"}}");tEle.replaceWith(h2);}}; }); </script>

原文出處 AngularJS - 自定義指令

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的AngularJS - 自定义指令的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。