自定義指令的各種屬性詳解
1. 通過 module.directive(name,directiveFactory) 定義 , 如:
(function() { angular.module('starter') .directive('myCustomer', function() { return { restrict: 'E', templateUrl: 'directiveTest/my-customer.html' }; }) })()
2. 注入 $compileProvider ,通過 $compileProvide.directive() 定義 , 如:
var myApp = angular.module('myApp', [], ['$compileProvider',function ($compileProvider) { $compileProvider.directive('customTags',function(){ return { restrict:'ECAM', template:'<div>custom-tags-html</div>', replace:false } }); }])
【二】 restrict 、 template 、 replace、templateUrl屬性
【三】transclude、priority、terminal 屬性var myApp = angular.module('myApp', [], ['$compileProvider',function ($compileProvider) { // 如果指令的名字為xxx-yyy 在設定指令的名字時應為 xxxYyy 駝峰式命名法 $compileProvider.directive('customTags',function(){ return { restrict:'ECAM', template:'<div>custom-tags-html</div>', replace:false, // templateUrl :載入模板所要使用的URL //replace :如果為true 則替換指令所在的元素,如果為false 或者不指定,則把當前指令追加到所在元素的內部 //restrict :指令在模板中的使用方式 //可以4種風格任意組合,如果忽略restrict,預設為A // E : 風格為 元素 (作為標籤名) 使用方式: <custom-tags>1212</custom-tags> // C: 風格為 樣式類 使用方式: <div class="custom-tags"> </div> // A : 風格為 屬性 使用方式: <div custom-tags> </div> // M : 風格為 註釋 // 注意:當有兩個directive的時候 只能有一個template,否則會報錯 } }); }])
priority : 設定指令在模板中的執行順序,順序是相對於其他元素上的指令而言,預設為0,從大到小的順序一次執行
terminal : 是否以當前指令的權重為結束界限。如果這個值設定為true,則節點中權重小於當前指令的其他指令不會被執行。相同權重的會執行
.directive('customTags', function () {
return {
restrict: 'ECAM',
template:'<div>新資料 <span ng-transclude></span></div>',
replace: true,
transclude:true
//transclude:為true時,指令元素中的原來的子節點移動到一個新模板內部(移動到的位置通過ng-transclude確定)
//priority 設定優先順序
}
})
.directive('customTags2', function () {
return {
restrict: 'ECAM',
template:'<div>2</div>',
replace: true,
priority:0
}
})
.directive('customTags3', function () {
return {
restrict: 'ECAM',
template:'<div>3</div>',
replace: true,
priority: 1,
// terminal 為true 時 priority 小於當前指令的priority的directive 都不會執行
terminal:true
}
})
【四】 compile 和 link 屬性
Angularjs 指令編譯三個階段
1.標準瀏覽器API轉化
將html 轉化成dom ,所以自定義的html 標籤必須符合html 的格式
2.Angular compile
搜尋匹配 directive ,按照priority排序,並執行directive上的compile 方法
3.Angular link
執行directive上的link 方法,進行 scope繫結及事件繫結
link 函式負責在模型和檢視之間進行動態關聯
.directive('customTags',function(){
return {
restrict : 'ECAM',
template : '<div>{{user.name}}</div>',
replace : true,
compile:function(tElement,tAttrs,transclude){
// 1.編譯階段...主要可以進行DOM 結構的操作
// tElement.append(angular.element('<div>{{user.name}}{{user.count}}</div>'));
console.log('customTags compile 編譯階段...');
return {
//2.Link 包括 pre 和 post 主要可以用在新增事件的繫結和scope繫結
// 2.1.1表示在編譯階段之後,指令連線到子元素之前執行
pre:function preLink(scope,iElement,iAttrs,controller){
console.log('customTags preLink..')
},
// 2.1.2表示在所有子元素指令都連線之後才執行
post:function postLink(scope,iElement,iAttrs,controller){
iElement.on('click',function(){
//需要用 $apply觸發一次 髒檢查
scope.$apply(function(){
scope.user.name = 'click after';
scope.user.count = ++i;
});
})
console.log('customTags all child directive link..')
}
}
// 也可以直接返回 postLink
// return function postction(scope,iElement,iAttrs,controller){
// console.log('compile return fun');
// }
},
// 此link表示的就是 postLink
// link:function postction(scope,iElement,iAttrs,controller){
// iElement.on('click',function(){
// scope.$apply(function(){
// scope.user.name = 'click after';
// scope.user.count = ++i;
// // 進行一次 髒檢查
// });
// })
// }
}
})
【五】controller 、controllerAs 和 require 屬性 .directive('bookList', function() {
return {
restrict: 'ECAM',
// controller 會暴露一個API ,利用這個API 可以在多個指令之間通過依賴注入進行通訊
controller: function($scope) {
$scope.books = [{
name: 'php'
}, {
name: 'javascript'
}, {
name: 'java'
}];
this.addBook = function() {
$scope.$apply(function() {
$scope.books.push({
name: 'Angularjs'
})
});
}
},
controllerAs: 'bookListController',//controllerAs:給上面的controller 起個別名
template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul><book-add></book-add></div>',
replace: true
}
})
.directive('bookAdd', function() {
return {
restrict: 'ECAM',
require: '^bookList',
//require 可以將其他指令傳遞給自己 ,如此可以去呼叫其他的指令的函式和修改其他指令的欄位,實現不同指令之間的通訊
// (沒有字首)如果沒有字首,指令將會在自身所提供的控制器中進行查詢,如果沒有找到任何控制器就丟擲一個錯誤。
// ? 如果在當前指令中沒有找到所需要的控制器,會將null作為傳給link函式的第四個引數。
// ^ 如果添加了^字首,指令會在上游的指令鏈中查詢require引數所指定的控制器。
// ?^ 將前面兩個選項的行為組合起來,我們可選擇地載入需要的指令並在父指令鏈中進行查詢。
template: '<button type="button">新增</button>',
replace: true,
link: function(scope, iElement, iAttrs, bookListController) {
//點選呼叫第一個指令的addBook函式
iElement.on('click', bookListController.addBook);
}
}
})
【六】 scope 屬性
scope : 為當前指令建立一個新的作用域
false : 繼承父元素的作用域
true : 建立一個新的作用域
引數:
&:作用域把父作用域的屬性包裝成一個函式,從而以函式的方式讀寫父作用域的屬性
=: 作用域的屬性與父作用域的屬性進行雙向繫結,任何一方的修改均會影響到對方
@:只能讀取父作用域裡的值單項繫結
.directive('bookList', function () {
return {
restrict: 'ECAM',
controller: function ($scope) {
$scope.books = $scope.a();
$scope.books = $scope.b;
$scope.b.push({name:'nodejs'});
console.log($scope.c);
},
// 建立一個有繼承鏈的獨立作用域
// scope:true,
// 當scope 為物件的時獨立的作用域候也會建立一個
scope:{
// 將父元素books封裝成一個a函式(&:作用域把父作用域的屬性包裝成一個函式,從而以函式的方式讀寫父作用域的屬性)
a:'&books'
// 雙向繫結 b = parentBooks屬性對應的父作用域的表示式(=:作用域的屬性與父作用域的屬性進行雙向繫結,
// 任何一方的修改均會影響到對方)
b:'=parentBooks'
// 只能使用簡單資料型別的方法,不能用物件(@ :只能讀取父作用域裡的值單向繫結)
c:'@parentTitle'
},
controllerAs:'bookListController',
template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul></div>',
replace:true
}
})
.controller('firstController', ['$scope', function ($scope) {
console.log($scope);
$scope.books = [
{
name: 'php'
},
{
name: 'javascript'
},
{
name: 'java'
}
];
$scope.title = '張三';
}]);
注意:html 檔案中的屬性寫法要與指令中定義的相匹配。以上面的為例,html中:
<div book-list books="books" parent-books="books" parent-title="{{title}}">