Directive多是AngularJS中比較複雜的一個東西了。通常咱們將其理解成指令。AngularJS自帶了很多預設的指令,好比ng-app,ng-controller這些。能夠發現個特色,AngularJS自帶的指令都是由ng-打頭的。javascript
那麼,Directive到底是個怎麼樣的一個東西呢?我我的的理解是這樣的:將一段html、js封裝在一塊兒,造成一個可複用的獨立個體,具體特定的功能。下面咱們來詳細解讀一下Directive的通常性用法。html
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 {
name: '',
priority: 0,
terminal: true,
scope: {},
controller: fn,
require: fn,
restrict: '',
template: '',
templateUrl: '',
replace: '',
transclude: true,
compile: fn,
link: fn
}
複製代碼
如上所示,return的對象中會有不少的屬性,這行屬性都是用來定義directive的。java
name
jquery
priority
angularjs
teminal
express
scope
segmentfault
true
{}
controller
bash
require
app
restrict
異步
template
templateUrl
replace
transclude
true/false
轉換這個directive的內容。(這個感受上,是直接將內容編譯後搬入指定地方)‘element’
轉換整個元素,包括其餘優先級較低的directive。(像將總體內容編譯後,看成一個總體(外面再包裹p),插入到指定地方)compile
link
這裏關於directive的scope爲一個object時,有更多的內容很是有必要說明一下。看下面的代碼:
scope: {
name: '=',
age: '=',
sex: '@',
say: '&'
}
複製代碼
這個scope中關於各類屬性的配置出現了一些奇怪的前綴符號,有=,@,&,那麼這些符號具體的含義是什麼呢?再看下面的代碼:
<div my-directive name="myName" age="myAge" sex="male" say="say()"></div>
複製代碼
function Controller($scope) {
$scope.name = 'Pajjket';
$scope.age = 99;
$scope.sex = '我是男的';
$scope.say = function() {
alert('Hello,我是彈出消息');
};
}
複製代碼
=
: 指令中的屬性取值爲Controller中對應$scope上屬性的取值@
: 指令中的取值爲html中的字面量/直接量&
: 指令中的取值爲Controller中對應$scope上的屬性,可是這個屬性必須爲一個函數回調 下面是更加官方的解釋:=
或者=expression/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的scope定義爲:{localFn:’increment()’},那麼isolate scope property localFn會指向一個包裹着increment()表達式的function。 通常來講,咱們但願經過一個表達式,將數據從isolate scope傳到parent scope中。這能夠經過傳送一個本地變量鍵值的映射到表達式的wrapper函數中來完成。例如,若是表達式是increment(amount),那麼咱們能夠經過localFn({amount:22})的方式調用localFn以指定amount的值。
下面的示例都圍繞着上面所做的參數說明而展開的。
// 自定義directive
var myDirective = angular.modeule('directives', []);
myDirective.directive('myTest', function() {
return {
restrict: 'EMAC',
require: '^ngModel',
scope: {
ngModel: '='
},
template: '<div><h4>Weather for {{ngModel}}</h4</div>'
};
});
// 定義controller
var myControllers = angular.module('controllers', []);
myControllers.controller('testController', [
'$scope',
function($scope) {
$scope.name = 'this is directive1';
}
]);
var app = angular.module('testApp', [
'directives',
'controllers'
]);
<body ng-app="testApp">
<div ng-controller="testController">
<input type="text" ng-model="city" placeholder="Enter a city" />
<my-test ng-model="city" ></my-test>
<span my-test="exp" ng-model="city"></span>
<span ng-model="city"></span>
</div>
</body>
複製代碼
templateUrl其實根template功能是同樣的,只不過templateUrl加載一個html文件,上例中,咱們也能發現問題,template後面根的是html的標籤,若是標籤不少呢,那就比較不爽了。能夠將上例中的,template改一下。
myDirective.directive('myTest', function() {
return {
restrict: 'EMAC',
require: '^ngModel',
scope: {
ngModel: '='
},
templateUrl:'../partials/tem1.html' //tem1.html中的內容就是上例中template的內容。
}
});
複製代碼
//directives.js中定義myAttr
myDirectives.directive('myAttr', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
template: 'Name: {{customerInfo.name}} Address: {{customerInfo.address}}<br>' +
'Name: {{vojta.name}} Address: {{vojta.address}}'
};
});
//controller.js中定義attrtest
myControllers.controller('attrtest',['$scope',
function($scope) {
$scope.naomi = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
$scope.vojta = {
name: 'Vojta',
address: '3456 Somewhere Else'
};
}
]);
// html中
<body ng-app="testApp">
<div ng-controller="attrtest"> <my-attr info="naomi"></my-attr> </div> </body>
複製代碼
Name: Naomi Address: 1600 Amphitheatre //有值,由於customerInfo定義過的
Name: Address: //沒值 ,由於scope重定義後,vojta是沒有定義的
複製代碼
myDirectives.directive('myAttr', function() {
return {
restrict: 'E',
template: 'Name: {{customerInfo.name}} Address: {{customerInfo.address}}<br>' +
'Name: {{vojta.name}} Address: {{vojta.address}}'
};
});
複製代碼
Name: Address:
Name: Vojta Address: 3456 Somewhere Else
複製代碼
由於此時的directive沒有定義獨立的scope,customerInfo是undefined,因此結果正好與上面相反。
myDirective.directive('myEvent', function() {
return {
restrict: 'E',
transclude: true,
scope: {
'close': '$onClick' //根html中的on-click="hideDialog()"有關聯關係
},
templateUrl: '../partials/event_part.html'
};
});
myController.controller('eventTest', [
'$scope',
'$timeout',
function($scope, $timeout) {
$scope.name = 'Tobias';
$scope.hideDialog = function() {
$scope.dialogIsHidden = true;
$timeout(function() {
$scope.dialogIsHidden = false;
}, 2000);
};
}
]);
複製代碼
<body ng-app="phonecatApp">
<div ng-controller="eventtest">
<my-event ng-hide="dialogIsHidden" on-click="hideDialog()">
Check out the contents, {{name}}!
</my-event>
</div>
</body>
<!--event_part.html -->
<div>
<a href ng-click="close()">×</a>
<div ng-transclude></div>
</div>
複製代碼
<body ng-app="phonecatApp">
<div ng-controller="eventtest">
<div ng-hide="dialogIsHidden" on-click="hideDialog()">
<span>Check out the contents, {{name}}!</span>
</div>
</div>
</body>
複製代碼
controller
,link
,compile
之間的關係myDirective.directive('exampleDirective', function() {
return {
restrict: 'E',
template: '<p>Hello {{number}}!</p>',
controller: function($scope, $element){
$scope.number = $scope.number + "22222 ";
},
link: function(scope, el, attr) {
scope.number = scope.number + "33333 ";
},
compile: function(element, attributes) {
return {
pre: function preLink(scope, element, attributes) {
scope.number = scope.number + "44444 ";
},
post: function postLink(scope, element, attributes) {
scope.number = scope.number + "55555 ";
}
};
}
}
});
//controller.js添加
myController.controller('directive2',[
'$scope',
function($scope) {
$scope.number = '1111 ';
}
]);
//html
<body ng-app="testApp">
<div ng-controller="directive2"> <example-directive></example-directive> </div> </body>
複製代碼
Hello 1111 22222 44444 5555 !
複製代碼
由結果能夠看出來,controller先運行,compile後運行,link不運行。 咱們如今將compile屬性註釋掉後,獲得的運行結果以下:
Hello 1111 22222 33333
!