AngularJs directive(指令)

AngularJs directive(指令)

返回的是一个对象,对象里面定义了一些属性,方法

var appModule = angular.module('app', []);
appModule.directive('hello', function() {
    return {
        restrict: 'E',			//restrict:指令方式选择
        template: '<div>Hi there</div>',//模板(要替换的内容)
        replace: true	//true表示HTML中不再有<hello>这个标签
    };
});



1.restrict
指令方式选择
"E":元素名
"A":属性
"C":类名
"M":注释


2.template
模板(要替换的内容)


3.templateUrl
模板,从而可以把模板写到一个独立的HTML文件中


4.replace
true表示替换掉标签(就是HTML中不再有<hello>这个标签),当然就算有,因浏览器不能识别所以也不会显示出来


5.priority
(数字),可选参数,指明指令的优先级,若在单个DOM上有多个指令,则优先级高的先执行;


6.terminal
(布尔型),可选参数,可以被设置为true或false,若设置为true,则优先级低于此指令的其他指令则无效,不会被
调用(优先级相同的还是会执行)


7.scope
(1)默认值false。表示继承父作用域;
当为false时候,儿子继承父亲的值,改变父亲的值,儿子的值也随之变化,反之亦如此。(继承不隔离)
(2)true。表示继承父作用域,并创建自己的作用域(子作用域);
当为true时候,儿子继承父亲的值,改变父亲的值,儿子的值随之变化,但是改变儿子的值,父亲的值不变。(继承隔离)
(3){}。表示创建一个全新的隔离作用域;
当为{}时候,没有继承父亲的值,所以儿子的值为空,改变任何一方的值均不能影响另一方的值。(不继承隔离)

隔离作用域可以通过绑定策略来访问父作用域的属性。
提供了三种方法同隔离之外的地方交互:
1.@ 绑定一个局部 scope 属性到当前 dom 节点的属性值。结果总是一个字符串,因为 dom 属性是字符串。
2.& 提供一种方式执行一个表达式在父 scope 的上下文中。如果没有指定 attr 名称,则属性名称为相同的本地名称。
3.= 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。


@ 局部 scope 属性
@ 方式局部属性用来访问 directive 外部环境定义的字符串值,主要是通过 directive 所在的标签属性绑定外部字符串值。
这种绑定是单向的,即父 scope 的绑定变化,directive 中的 scope 的属性会同步变化,而隔离 scope 中的绑定变化,
父 scope 是不知道的。

$scope.name = "hello world"; //父scope

<div isolated-directive name="{{name}}"></div>

scope: { //子scope
 name: "@"  //使用@绑定 name 属性
 }



= 局部 scope 属性
= 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。
意思是,当你想要一个双向绑定的属性的时候,你可以使用=来引入外部属性。无论是改变父 scope 还是隔离 scope 里的属性,
父 scope 和隔离 scope 都会同时更新属性值,因为它们是双向绑定的关系。

$scope.userBase = { //父scope
 name: 'hello',
 id: 1
}

<div isolated-directive user="userBase"></div>

scope: { //子scope
 user: "=" //使用@绑定 name 属性
}



& 局部 scope 属性
& 方式提供一种途经是 directive 能在父 scope 的上下文中执行一个表达式。此表达式可以是一个 function。
比如当你写了一个 directive,当用户点击按钮时,directive 想要通知 controller,controller 无法知道
directive 中发生了什么,也许你可以通过使用 angular 中的 event 广播来做到,但是必须要在 controller
中增加一个事件监听方法。
最好的方法就是让 directive 可以通过一个父 scope 中的 function,当 directive 中有什么动作需要更新到
父 scope 中的时候,可以在父 scope 上下文中执行一段代码或者一个函数。

$scope.click = function () { //父scope
$scope.value = Math.random();
}

<div isolated-directive action="click()"></div>

scope: { //子scope
action: "&"
}



8.transclude
如果不想让指令内部的内容被模板替换,可以设置这个值为true。一般情况下需要和ngTransclude指令一起使用。 比如:
template:"<div>hello every <div ng-transclude></div></div>",这时,指令内部的内容会嵌入到ng-transclude这个
div中。也就是变成了<div>hello every <div>这是指令内部的内容</div></div>。默认值为false;这个配置选项可以让
我们提取包含在指令那个元素里面的内容,再将它放置在指令模板的特定位置。当你开启transclude后,你就可以使用
ng-transclude来指明了应该在什么地方放置transcluded内容

就是引用这个指令里的内容会被放入到指令模板ng-transclude处的位置,如是为false引用这个指令里的内容会全部被替换掉


9.controller
可以是一个字符串或者函数。
若是为字符串,则将字符串当做是控制器的名字,来查找注册在应用中的控制器的构造函数

另外还有一些特殊的服务(参数)可以注入
(1)$scope,与指令元素相关联的作用域
(2)$element,当前指令对应的 元素
(3)$attrs,由当前元素的属性组成的对象
(4)$transclude,嵌入链接函数,实际被执行用来克隆元素和操作DOM的函数


10.controllerAs
这个选项的作用是可以设置你的控制器的别名


11.require(字符串或者数组)(很少会用到)


12.Anguar的指令编译过程
1.首先加载angularjs库,查找到ng-app指令,从而找到应用的边界,
2.根据ng-app划定的作用域来调用$compile服务进行编译,angularjs会遍历整个HTML文档,并根据js中指令的定义来处理在
页面上声明的各个指令按照指令的优先级(priority)排列
3.根据指令中的配置参数(template,place,transclude等)转换DOM然后就开始按顺序执行各指令的compile函数(如果指令
上有定义compile函数)对模板自身进行转换
4.注意:此处的compile函数是我们指令中配置的,跟上面说的$compile服务不一样。每个compile函数执行完后都会返回一个
link函数,所有的link函数会合成一个大的link函数
5.然后这个大的link函数就会被执行,主要做数据绑定,通过在DOM上注册监听器来动态修改scope中的数据,或者是使用
$watchs监听 scope中的变量来修改DOM,从而建立双向绑定等等。
6.若我们的指令中没有配置compile函数,那我们配置的link函数就会运行,她做的事情大致跟上面complie返回之后所有的
link函数合成的的大的link函数差不多。
7.所以:在指令中compile与link选项是互斥的,如果同时设置了这两个选项,那么就会把compile所返回的函数当做是链接
函数,而link选项本身就会被忽略掉


13、编译函数 Compile function(很少会用到)
function compile(tElement, tAttrs, transclude) { ... }
编译函数是用来处理需要修改模板DOM的情况的。因为大部分指令都不需要修改模板,所以这个函数也不常用。需要用到的例
子有ngTrepeat,这个是需要修改模板的,还有ngView这个是需要异步载入内容的。编译函数接受以下参数。
tElement - template element - 指令所在的元素。对这个元素及其子元素进行变形之类的操作是安全的。
tAttrs - template attributes - 这个元素上所有指令声明的属性,这些属性都是在编译函数里共享的。
transclude - 一个嵌入的链接函数function(scope, cloneLinkingFn)。
注意:在编译函数里面不要进行任何DOM变形之外的操作。 更重要的,DOM监听事件的注册应该在链接函数中做,而不是编译函数中。
编译函数可以返回一个对象或者函数。
返回函数 - 等效于在编译函数不存在时,使用配置对象的link属性注册的链接函数。
返回对象 - 返回一个通过pre或post属性注册了函数的对象。参考下面pre-linking和post-liking函数的解释。


14、链接函数 Linking function(很少会用到)
function link(scope, iElement, iAttrs, controller) { ... }
链接函数负责注册DOM事件和更新DOM。它是在模板被克隆之后执行的,它也是大部分指令逻辑代码编写的地方。
scope - 指令需要监听的作用域。
iElement - instance element - 指令所在的元素。只有在postLink函数中对元素的子元素进行操作才是安全的,因为那时它们才已经全部链接好。
iAttrs - instance attributes - 实例属性,一个标准化的、所有声明在当前元素上的属性列表,这些属性在所有链接函数间是共享的。
controller - 控制器实例,也就是当前指令通过require请求的指令direct2内部的controller。比如:direct2指令中的
controller:function(){this.addStrength = function(){}},那么,在当前指令的link函数中,你就可以通过controller.addStrength进行调用了。
Pre-linking function 在子元素被链接前执行。不能用来进行DOM的变形,以防链接函数找不到正确的元素来链接。
Post-linking function 所有元素都被链接后执行。



参考原文: http://www.jb51.net/article/83051.htm

猜你喜欢

转载自huangyongxing310.iteye.com/blog/2324235