Angular之指令Directive用法詳解
項目籌備近期開啟Angular學習,指令比較難理解所以記錄備案,推薦視頻大漠窮秋 Angular實戰(zhàn) 由于篇幅過長,列舉大綱如下:
一、指令directive概述
指令可以對元素綁定事件監(jiān)聽或者改變DOM結構而使HTML擁有像jQuery一樣效果具有交互性。不同于jQuery,Angular設計核心思想是通過數(shù)據(jù)與模板的綁定,擺脫繁瑣的DOM操作,而將注意力集中在業(yè)務邏輯上。
幾種常見指令ng-app 指令用來指定ng的作用域是在那個標簽以內(nèi)部分(<html ng-app="myApp">標簽) ng-repeat迭代器指令可以重復標記元素、ng-show指令可以根據(jù)條件是否顯示一個元素、ng-model指令具有雙向數(shù)據(jù)綁定特性、ng-controller 用來聲明一個需要和數(shù)據(jù)進行綁定的模板區(qū)域
二、自定義指令directive之模式匹配restrict
直接上代碼體驗一把,index.html
<!DOCTYPE html> <html ng-app="myModule"> <head> <meta charset="UTF-8"> <title>Angular指令--自定義標簽</title> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> </head> <body> <hello></hello> <div hello></div> <div class='hello'></div> <!-- directive:hello --> <div></div> <!--代碼模板template--> <script type="text/ng-template" id="hello_Angular.html"> <p>Hello Angular</p> </script> <!--代碼模板template--> </body> </html>
指令Directive.js
<script type="text/javascript"> //調(diào)用angular對象的module方法來聲明一個模塊,模塊的名字和ng-app的值對應 var myModule = angular.module('myModule',[]); /* restrict 屬性值說明 <推薦使用EA> * E--element元素 <hello></hello> * A--attribute 屬性 <div hello></div> * C-class 樣式類 <div class="hello"></div> * M 注釋 <!-- directive:hello --> */ //指令--對元素綁定事件監(jiān)聽或者改變DOM myModule.directive('hello', function(){ return { restrict: 'EACM', templateUrl:'hello_Angular.html', /*template : '<p>Hello Angular</p>',*/ replace: true } }) </script>
==========================================================
restrict---匹配模式說明, 英文意思是"限制;約束;限定",這里指的是匹配我自定義的標簽
==========================================================
•E 元素(element) <hello></hello>
•A 屬性(attribute) <div hello></div>
•C 樣式類(class) <div class="hello"></div>
•M 注釋 <!-- directive:hello --> 注意?。?!空格(不常用)
溫馨tips: 推薦使用EC或EA匹配模式
replace 是否替換元素的模式 replace:true瀏覽器DOM結構如下
replace:false 或沒有replace屬性時瀏覽器DOM結構如下
三、指令之嵌套變換transclude
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="UTF-8"> <title>transclude 嵌套變換</title> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> </head> <body> <hello>這里是內(nèi)容哦.....</hello> <div hello>這里是內(nèi)容哦hello....</div> <script type="text/javascript"> var myApp = angular.module('myApp', []); myApp.directive('hello',function(){ return { restrict: 'EA', template: '<p>Hello World!!!<b ng-transclude></b></p>', transclude: true, /*嵌套變換*/ replace: true /*替換*/ } }) </script> </body> </html>
四、指令directive運行原理
五、指令配置參數(shù)說明
myModule.directive('namespaceDirectiveName', function factory(injectables) { var directiveDefinitionObject = { restrict: string,//指令的使用方式,包括標簽,屬性,類,注釋 priority: number,//指令執(zhí)行的優(yōu)先級 template: string,//指令使用的模板,用HTML字符串的形式表示 templateUrl: string,//從指定的url地址加載模板或<script type="text/ng-template" id="string"></script> replace: bool,//是否用模板替換當前元素,若為false,則append在當前元素上 transclude: bool,//是否將當前元素的內(nèi)容轉移到模板中 scope: bool or object,//指定指令的作用域 controller: function controllerConstructor($scope, $element, $attrs, $transclude){...},//定義與其他指令進行交互的接口函數(shù) require: string,//指定需要依賴的其他指令 link: function postLink(scope, iElement, iAttrs) {...},//以編程的方式操作DOM,包括添加監(jiān)聽器等 compile: function compile(tElement, tAttrs, transclude){ return: { pre: function preLink(scope, iElement, iAttrs, controller){...}, post: function postLink(scope, iElement, iAttrs, controller){...} } }//編程的方式修改DOM模板的副本,可以返回鏈接函數(shù) }; return directiveDefinitionObject; });
六、指令與控制器的交互
index.html 如下
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="UTF-8"> <title>Directive指令與Controller控制器交互</title> <!--引入js庫anglarjs--> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> <script type="text/javascript" src="js/Directive&Controller.js"></script> </head> <body> <div ng-controller="myAppCtrl"> <loader hello howToLoad="loadData()">數(shù)據(jù)加載......</loader> </div> <div ng-controller="myAppCtrl2"> <loader hello howToLoad="loadData2()">數(shù)據(jù)加載2......</loader> </div> </body> </html>
Directive&Controller.js
var myApp = angular.module('myApp', []); myApp.controller('myAppCtrl', ['$scope', function($scope){ console.log($scope); $scope.loadData = function(){ console.log('數(shù)據(jù)加載中.....'); } }]); myApp.controller('myAppCtrl2', ['$scope', function($scope){ console.log($scope); $scope.loadData2 = function(){ console.log('數(shù)據(jù)加載中2.....'); } }]); //指令與控制器之間交互 myApp.directive('loader', function(){ return { restrict: 'EA', template: '<div ng-transclude></div>', transclude: true, replace: true, /*scope: {}, 獨立scope*/ link: function(scope, element, attrs){ element.bind('mouseenter', function(){ /*這里調(diào)用controller中的方法三種方式*/ /*(1) scope.loadData(); (2) scope.$apply('loadData()'); (3) attrs.howtoload === 屬性上綁定的函數(shù)名稱*/ //屬性方式 注意坑!??! howtoload 得小寫 scope.$apply(attrs.howtoload); }) } } })
實現(xiàn)的效果是當鼠標滑過div元素時,調(diào)用一個加載數(shù)據(jù)的方法。
上述例子中定義了兩個控制器,然后兩個控制器中都使用了loader指令,并且,每個指令中都有一個參數(shù) howToLoad .
關于指令中的 link ,上面介紹運行機制中可以了解到,link: function postLink(scope, element, attrs) {...}是用來操作dom和綁定監(jiān)聽事件的。
link中會有三個參數(shù):scope(指令所屬的控制器中的 $scope 對象)、element(指令所屬dom元素)、attrs(dom元素所傳的參數(shù)
如howToLoad 參數(shù)給的值 loadData()
然后對于如何調(diào)用所需函數(shù),有兩種方法:
1> scope.loadData() 兩個控制器方法不一致時,就不能用了
2> scope.$apply() $apply()方法會從所有控制器中找到多對應的方法。這就實現(xiàn)了指令的復用。
明確對于控制器ng-controller都會創(chuàng)建屬于自己獨立的scope;對于指令若無scope:{}聲明會繼承控制器中的scope
七、指令與指令的交互
index.html
<!DOCTYPE html> <html ng-app="myModule"> <head> <meta charset="UTF-8"> <title>directive指令與directive指令之間的交互</title> <!--引入第三方樣式庫bootstrap.min.css--> <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" /> <!--引入js庫anglarjs--> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> <script type="text/javascript" src="js/Directive&Directive.js"></script> </head> <body> <div class="row"> <div class="col-md-3"> <superman strength>動感超人---力量</superman> </div> </div> <div class="row"> <div class="col-md-3"> <superman strength speed>動感超人2---力量+敏捷</superman> </div> </div> <div class="row"> <div class="col-md-3"> <superman strength speed light>動感超人3---力量+敏捷+發(fā)光</superman> </div> </div> </body> </html>
Directive&Directive.js
var myModule = angular.module('myModule',[]); //指令與指令之間交互 myModule.directive('superman', function(){ return { scope: {},/*獨立作用域*/ restrict: 'AE', template: '<button class="btn btn-primary" ng-transclude></button>', transclude: true, controller: function($scope){ /*暴露controller里面方法*/ $scope.abilities = []; this.addStrength = function(){ $scope.abilities.push('strength'); }; this.addSpeed = function(){ $scope.abilities.push('speed'); }; this.addLight = function(){ $scope.abilities.push('light'); }; }, link: function(scope, element, attrs, supermanCtr){ element.addClass = "btn btn-primary"; element.bind('mouseenter', function(){ console.log(scope.abilities); }) } } }) myModule.directive('strength', function(){ return { require: "^superman",/*require參數(shù)指明需要依賴的指令*/ link: function(scope, element, attrs, supermanCtr){ supermanCtr.addStrength(); } } }); myModule.directive('speed', function(){ return { require: "^superman", link: function(scope, element, attrs, supermanCtr){ supermanCtr.addSpeed(); } } }); myModule.directive('light', function(){ return { require: "^superman", link: function(scope, element, attrs, supermanCtr){ supermanCtr.addLight(); } } });
*require參數(shù)指明需要依賴的指令
*指令中的controller相當于暴露里面方法,便于指令復用
八、scope作用域綁定策略
scope “@” 把當前屬性作為字符串傳值
<!DOCTYPE html> <html ng-app="myModule"> <head> <meta charset="UTF-8"> <title>scope綁值策略一.'@'把當前屬性作為字符串傳值</title> <!--引入js庫anglarjs--> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> <script type="text/javascript" src="js/Scope@.js"></script> </head> <body> <div ng-controller="myAppCtrl"> <drink flavor="{{ctrFlavor}}"></drink> </div> </body> </html>
Scope@.js
var myModule = angular.module('myModule', []); myModule.controller('myAppCtrl',['$scope', function($scope){ console.log($scope); $scope.ctrFlavor = "百事可樂"; }]); myModule.directive('drink', function(){ return { restrict: 'AE', scope: { /*獨立scope作用域*/ flavor: '@' }, replace:true, template: '<p>{{flavor}}</p>' //使用link進行指令和控制器兩個作用域中數(shù)據(jù)的綁定。 //如果用scope中@的話,就不需要link這么麻煩了,angularJS會自動進行綁定 /*, link:function(scope,element,attrs){ element.bind('mouseenter', function(){ }) scope.flavor = attrs.flavor; }*/ } })
scope “=” 與父scope屬性進行雙向綁定
index.html
<!DOCTYPE html> <html ng-app="myModule"> <head> <meta charset="UTF-8"> <title>scope綁值策略二.'='與父scope中的屬性進行雙向綁定</title> <!--引入第三方樣式庫bootstrap.min.css--> <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" /> <!--引入js庫anglarjs--> <script type="text/javascript" src="js/scope=.js"></script> </head> <body> <div ng-controller="myModuleCtrl" class="col-sm-6"> <p>{{describe}}</p> Ctrl--控制器:<br /> <input type="text" ng-model="ctrFlavor" class="form-control" /> <br /> <p>{{ctrFlavor}}</p> Directive--指令:<br /> <drink flavor="ctrFlavor"></drink> <p>{{flavor}}</p> </div> </body> </html>
scope=.js
var myModule = angular.module('myModule', []); myModule.controller('myModuleCtrl',['$scope', function($scope){ $scope.describe = "scope綁值策略二.=與父scope中的屬性進行雙向綁定"; $scope.ctrFlavor = "可口可樂"; }]); //=與父scope中的屬性進行雙向綁定 myModule.directive('drink',function(){ return { restrict: 'EA', scope: { /*ng-isolate-scope 隔離作用域*/ flavor : '=' }, template: '<input type="text" class="form-control" ng-model="flavor" />' /*replace:true*/ } });
這個例子中有兩個輸入框,第一個綁定了myModuleCtrl控制器中的scope對象的ctrlFlavor 屬性。
第二個綁定的是指令中的flavor屬性。但是在drink 指令中 scope對象的flavor 屬性 用了 ”=“ ,
與父scope中的屬性進行雙向數(shù)據(jù)綁定。所以兩個值有一個改動,另一個屬性值也會改動。 簡單理解為把兩個存放數(shù)據(jù)倉庫給相等 A1 == B1
scope& '&'傳遞一個來自父scope的函數(shù),稍后調(diào)用
index.html
<!DOCTYPE html> <html ng-app="myModule"> <head> <meta charset="UTF-8"> <title>scope綁值策略三.'&'傳遞一個來自父scope的函數(shù),稍后調(diào)用</title> <!--引入第三方樣式庫bootstrap.min.css--> <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" /> <!--引入js庫anglarjs--> <script type="text/javascript" src="js/scope&.js"></script> </head> <body> <div ng-controller="myModuleCtrl"> <greeting greet="sayHello(name)"></greeting> <greeting greet="sayHello(name)"></greeting> <greeting greet="sayHello(name)"></greeting> </div> <!--代碼模板template--> <script type="text/ng-template" id="sayHello.html"> <div class="col-sm-12 container"> <form role = "form"> <div class = "form-group"> <input type="text" class="form-control" ng-model="userName" /> <button class="btn btn-primary" ng-click="greet({name:userName})">Greeting</button> </div> </form> </div> </script> <!--代碼模板template--> </body> </html>
scope&.js
var myModule = angular.module('myModule', []); myModule.controller('myModuleCtrl',['$scope', function($scope){ $scope.sayHello = function(name){ console.log('Hello'+name); } }]); myModule.directive('greeting', function(){ return { restrict: 'EA', scope: { /*'&'傳遞一個來自父scope的函數(shù),稍后調(diào)用*/ greet : '&' }, templateUrl: 'sayHello.html' } });
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Angular2中如何使用ngx-translate進行國際化
本篇文章主要介紹了Angular2中使用ngx-translate進行國際化,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05基于angular中的重要指令詳解($eval,$parse和$compile)
下面小編就為大家?guī)硪黄赼ngular中的重要指令詳解($eval,$parse和$compile)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10Angular中ng-repeat與ul li的多層嵌套重復問題
這篇文章主要介紹了Angular中ng-repeat與ul li的多層嵌套重復問題,需要的朋友可以參考下2017-07-07