弁言
指令(Directive)能够说是 AngularJS
的中心,而其开辟也是比较难题的,本文重要引见指令的一些参数和scope的绑定战略。
参数
从 AngularJS 的官方文档中看到指令的参数以下:
{
priority: 0,
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// or
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
transclude: false,
restrict: 'A',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
controllerAs: 'stringAlias',
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
// or
// return function postLink( ... ) { ... }
},
// or
// link: {
// pre: function preLink(scope, iElement, iAttrs, controller) { ... },
// post: function postLink(scope, iElement, iAttrs, controller) { ... }
// }
// or
// link: function postLink( ... ) { ... }
}
下面细致解说每一个参数。
priority(Number)
指令实行的优先级,用于多个指令同时作用于同一个元素时。比方:
<select>
<option ng-repeat="i in [1, 2]" ng-bind="i"></option>
</select>
上面的例子中,ng-repeat
指令和 ng-bind
指令同时作用于 option
元素,由于 ng-repeat
的 priority 为1000,ng-bind
的 priority 为0,因而先实行 ng-repeat
,然后变量 i 的值才用于 ng-bind 中。
template(String or Function)
HTML模板内容,用于以下状况之一:
替代元素的内容(默许状况)。
替代元素自身(假如 replace 选项为 true)。
将元素的内容包裹起来(假如 transclude 选项为 true,背面会细说)。
值可所以:
一个 HTML 字符串。比方:
<div>my name is {{name}}</div>
。一个函数,吸收两个参数 tElement(元素自身) 和 tAttrs(元素的属性鸠合),返回 HTML 字符串。
templateUrl(String or Function)
templateUrl 和 template 作用雷同,但模板内容是从 $templateCache 效劳或长途 url 加载。
值可所以:
一个字符串,
AngularJS
会先从$templateCache
中查找是不是缓存了对应值,假如没有则尝试 ajax 加载。比方:在页面中有以下 script:<script type="text/ng-template" id="Hello.html"> <p>Hello</p> </script>
AngularJS 会将
type="text/ng-template"
的script
标签中的内容以 id 值为 key 缓存到 $templateCache 效劳中,此时能够设置templateUrl: 'Hello.html'
。一个函数,吸收两个参数 tElement(元素自身) 和 tAttrs(元素的属性鸠合),返回 url 地点。
transclude(Boolean)
官方文档的解释为:编译元素的内容,使其在指令内部可用。该选项平常和 ng-transclude
指令一同运用。
假如 transclude 设置为 true,则元素的内容会被放到模板中设置了 ng-transclude
指令的元素中。比方:
app.directive('testTransclude', [
function () {
return {
restrict: 'E',
transclude: true,
template:
'<div>\
<p>指令内部段落</p>\
<div ng-transclude></div>\
</div>'
};
}
]);
<test-transclude>
<p>该段落会被放到指令内部</p>
</test-transclude>
上面天生后的 DOM 构造为:
restrict(String)
指令的运用情势。
值能够为:
'E'
– 指令作为元素运用'A'
– 指令作为属性运用'C'
– 指令作为类名运用'M'
– 指令作为解释运用(不经常使用)
可所以以上值的组合,如 restrict: 'EA'
示意指令既能够作为属性运用,也能够作为元素运用。
scope(Boolean or Object)
关于 scope 选项将会在背面的指令 scope 中细说。
controller(Function)
平常状况下不须要运用指令的 controller
,只需运用 link
就够了,背面会细说 link 函数。
用 controller
的场景是该指令(a)会被其他指令(b)require
的时刻,在 b 的指令里能够传入 a 的这个 controller,目标是为了指令间的复用和交换。而 link
只能在指令内部中定义行动,没法做到如许。
controllerAs(String)
为控制器指定别号,如许能够在须要控制器的处所运用该名字举行注入。
require(String or Array)
示意指令依靠于一个或多个指令,并注入所依靠指令的控制器到 link
函数的第四个参数中。假如所依靠的指令不存在,或所依靠指令的控制器不存在则会报错。
依靠称号前缀能够为:
(没有前缀) – 在当前元素中查找依靠指令的控制器,假如不存在则报错。
?
– 在当前元素中查找依靠指令的控制器,假如不存在传null
到link
中。^
– 在当前元素及父元素中查找依靠指令的控制器,假如不存在则报错。?^
– 在当前元素及父元素中查找依靠指令的控制器,假如不存在传null
到link
中。
例子:
app.directive('validate', [
function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, ele, attrs, ngModelCtrl) {
// 监听值变化
ngModelCtrl.$viewChangeListeners.push(function () {
scope.validateResult = ngModelCtrl.$viewValue === 'Heron';
});
}
};
}
]);
app.controller('myCtrl', [
'$scope',
'$cookieStore',
function ($scope, $cookieStore) {
$scope.name = 'Heron';
$scope.sayHi = function (name, age) {
alert('Hello ' + name + ', your age is ' + age);
}
}
]);
<div ng-controller="myCtrl">
<input type="text" ng-model="name" validate>
<p>
validate 效果:{{validateResult}}
</p>
</div>
运转效果如图:
compile(Function)
和 link(Function)
竖立的竖立历程能够分为编译(compile)阶段和链接(link)阶段,因而二者放一同讲。
二者区分在于:
compile
函数的作用是对指令的模板举行转换。link
函数的作用是在视图和模子之间竖立关联,包含注册事宜监听函数和更新DOM
操纵。scope
在链接阶段才会被绑定到元素上,因而compile
函数中没有入参scope
。关于同一个指令的多个示例,
compile
函数只会实行一次,而link
函数在每一个实例中都邑实行。假如自定义了
compile
函数,则自定义的link
函数 无效,而是运用compile
函数 返回的link
函数。
指令 scope
scope 选项有三种值:
false
– 运用父scope
。转变父scope
会影响指令scope
,反之亦然。true
– 继续父scope
,并竖立本身的scope
。转变父scope
会影响指令scope
,而转变指令scope
不会影响父scope
。{}
– 不继续父scope
,竖立自力的scope
。假如不运用双向绑定战略(背面会讲),转变父scope
不会影响指令scope
,反之亦然。
例子:
app.controller('myCtrl', [
'$scope',
'$cookieStore',
function ($scope, $cookieStore) {
$scope.scopeFalse = 'Heron';
$scope.scopeTrue = 'Heron';
$scope.scopeObject = 'Heron';
}
]);
app.directive('directiveFalse', [
function () {
return {
restrict: 'EA',
scope: false,
template:
'<div>\
<p>\
<span>指令 scope: </span>\
<input type="text" ng-model="scopeFalse">\
</p>\
</div>'
};
}
]);
app.directive('directiveTrue', [
function () {
return {
restrict: 'EA',
scope: true,
template:
'<div>\
<p>\
<span>指令 scope: </span>\
<input type="text" ng-model="scopeTrue">\
</p>\
</div>'
};
}
]);
app.directive('directiveObject', [
function () {
return {
restrict: 'EA',
scope: {},
template:
'<div>\
<p>\
<span>指令 scope: </span>\
<input type="text" ng-model="scopeObject">\
</p>\
</div>',
link: function (scope) {
// 由于运用自力scope,因而须要本身定义变量
scope.scopeObject = 'Heron';
}
};
}
]);
<div ng-controller="myCtrl">
<h3>scope: false</h3>
<p>
<span>父 scope: </span>
<input type="text" ng-model="scopeFalse">
</p>
<directive-false></directive-false>
<h3>scope: true</h3>
<p>
<span>父 scope: </span>
<input type="text" ng-model="scopeTrue">
</p>
<directive-true></directive-true>
<h3>scope: {}</h3>
<p>
<span>父 scope: </span>
<input type="text" ng-model="scopeObject">
</p>
<directive-object></directive-object>
</div>
运转效果如图:
针对自力 scope,能够经由过程在对象中声明怎样从外部传入参数。有以下三种绑定战略:
@
– 运用 DOM 属性值单项绑定到指令scope
中。此时绑定的值老是一个字符串,由于DOM
的属性值是一个字符串。<div my-directive age="26"></div> scope: { age: '@' }
=
– 在父scope
和指令scope
之间竖立双向绑定。<div my-directive age="age"></div> scope: { age: '=' }
&
– 运用父scope
的高低文实行函数。平经常使用于绑定函数。<div my-directive sayHi="sayHi()"></div> scope: { sayHi: '&' }
绑定函数时,偶然须要向指令外部通报参数,以下:
app.controller('myCtrl', [
'$scope',
'$cookieStore',
function ($scope, $cookieStore) {
$scope.name = 'Heron';
$scope.sayHi = function (name, age) {
alert('Hello ' + name + ', your age is ' + age);
};
}
]);
app.directive('myDirective', [
function () {
return {
restrict: 'E',
replace: true,
scope: {
clickMe: '&'
},
template:
'<div>\
<button class="btn btn-info" ng-click="clickMe({ age: age })">点我</button>\
</div>',
link: function (scope) {
scope.age = 26;
}
};
}
]);
<div ng-controller="myCtrl">
<my-directive click-me="sayHi(name, age)"></my-directive>
</div>
运转效果如图:
申明一下:起首声明 clickMe: '&'
运用父 scope 的环境实行 clickMe 函数,然后在通报给指令时声明 click-me="sayHi(name, age)"
,示意父 scope 的 sayHi
要领须要两个参数,一个是 name,一个是 age,然后再指令中运用对象 {} 的体式格局向外通报参数,如 ng-click="clickMe({ age: age })"
,示意向指令外通报 age 参数,sayHi 要领从指令拿到 age 参数,再从本身的高低文中拿到 name 参数。
结语
AngularJS 指令的开辟和运用一成不变,也有很多坑,愿望人人注意,也愿望人人能在批评区多多交换心得。