先对自定义Directive有一个大体的映像

myModule.directive('myDirective',function(injectables){
var directiveDefinitionObject={
restrict:string,
priority:number,
template:string,
templateUrl:string,
replace:bool,
transclude:bool,
scope:bool or object,
controller:function controllerConstructor($scope,$element,$attrs,$transclude){...},
require:string,
link:function postLink(scope,iElement,iAttrs){...},
compile:function compile(tElement,tAttrs,transclude){
...
return {
pre:functionLink(scope,iElement,iAttrs,controller){...},
post:functionLink(scope,iElement,iAttrs,controller){...}
};
}
};
});

重点在directiveDefinitionObject这个对象。这个对象当中有些属性是互相排斥的,即:有了A属性,就不需要B属性。但大部分是可选的

以下是详细解释各个属性的作用
1. restrict: 决定directive是做HTML tag,属性,类或者是注释,只能在 'E','A','C','M'或者这四个字母的任意组合中取值。参考下表
    值      例子
    E        <my-directive></my-directive>
    A        <div my-directive='abc'></div>
    C        <div class='my-directive:abc'></div>
    M        <!--this is abc my-directive:abc -->
    restrict默认是A,如果一个directive既想用在Tag中也想用在注释中,那么就用 'EM'。

注意:Directive名字是myDirective,但是使用时,无论是在HTML tag,还是属性,还是类中都是 my-directive。 如果Directive名字是LoginInBar,那么使用时就用login-in-bar.(AngularJS会进行奇怪的名称转换)
2. priority 设置优先级,数字大的先运行。一个例子是ng-repeat ,必须要先跑ng-repeat,生产出重复的对象,再跑其他
3. template和templateUrl 模板或者模板地址。有时我们把一大段HTML片段包装在一个AngularJS中,如我只想用一个<hello></hello>来表示<div>hello <span style='color:red;'>world</span></div>那么可以把template设置为这一段字符串,或者写道另一个文件中用templateUrl引用。当然,还可以通过其他方法加载模板,然后把它们存在$templateCache中,如下。
   module.run(function($templateCache){
        $templateCache.put("a.html","<div>hello <span style='color:red;'>world</span></div>");
   });
4. transclude 有时我们想保留原始的内容,并把它们添加到模板中,如有<hello>,we have fun</hello>。 想实现的效果是<div>hello world, we have fun</div>。如果我们设置了template为

<div>hello world</div>,那么"we have fun"这一段不见了,现在设置transclude为true,并把template设置为<div>hello world<span ng-transclude></span></div>,就可以达成需要的效果了。注意template中多了个ng-transclude
5.compile和link
    AngularJS的directive要起作用必须经过两个阶段:
    1) compile阶段,在该阶段AngularJS搜寻template中的整个DOM树,找到所有注册的其他directive,把他们按照各自的templat、replace等设置转换为DOM,运行各自的compile的function
    2) link阶段,在该阶段主要负责保持model和view的一致性,就是各种加监听器。在这个阶段scope在被注入到link中,所有的directive才有用
    
    ...
    
6.scope AngularJS提供了三种scope给directive
    1).就用DOM中已经存在的scope  (false)
    2).继承自从已经存在的scope,可以访问父级scope中的所有properties  (true)
    3).一个独立的scope。不可以访问父级scope的properties ,但他有一个$parent属性指向父级scope  (一个{/*properties*/}对象)
    对于前两种没什么好说的,对于第三种,看一个例子。
    现在想完成一个点击之后显示一些div的功能。HTML代码如下:
    <div ng-controller='MyController'>
        <expander expand-title='title' expand-text='text' expand-click='change()'></expander>
    </div>
    javascript代码如下:

angular.module('test',[])
.controller('MyController',['$scope',function($scope){
$scope.title='click me i am the title';
$scope.text='well ,i was hidden but now i am shown';
$scope.change=function(){
$scope.text='haha i change myself';
};
}])
.directive('expander',function(){
return {
restrict:'E',
replace:true,
transclude:true,
template:['<div>',
'<div id="d1" ng-click="toggle()">{{scopeTitle}}</div>',
'<div id="d2" ng-show="showMe" ng-transclude>{{scopeText}}</div>',
'<div id='d3' ng-click="scopeChange()">click me to change</div>',
'</div>'].join(''),
scope:{scopeTitle:'@expandTitle',
scopeText:'=expandText',
scopeChange:'&expandClick'},
link:function(scope,element,attributes){
scope.showMe=false;
scope.toggle=function(){
scope.showMe=!scope.showMe;
};
}
};
})
;

结果是在d1中显示的是title,因为scopeTitle取得是'@expandTitle',意思是把expand-title的属性值当作字符串传给scopeTitle;

而d2中显示的是“well ,i was hidden but now i am shown”,因为scopeText取得是'=expandText',意思是把expand-text的值当作变量名,在父级scope中找到同名的变量,把这个变量的值传给           scopeText;
    再看d3中的ng-click,它的值是通过scopeChange:'&expandClick'传进来的,expand-click的值是父级scope中的scope方法。所以’&'可以用来传递方法。

4.controller directives之间需要互相通信是,可以通过controller来进行
    controller: function($scope,$element,$attrs,$transclude){}
    其他的directive可以接受这个controller:通过require属性 require:"^?directiveName".
    directiveName:是驼峰表示法的directive的名字。需要哪个directive的controller就写哪个的名字;
    ^:默认的AngularJS是找同一个元素内的directive,如果加上了“^”,AngularJS沿着DOM树往上找,知道找到为止;
    ?:如果没找到controller,AngularJS会丢出一个错误,加上了"?"表示没找到也没关系;
    重写一个例子,要求出现三个tag,点击其中一个的话,自己展开,别的收缩

angular.module('test',[])
.directive('accordion',function(){
return {
restrict:"E",
replace:true,
transclude:true,
template:'<div ng-transclude></div>',
controller:function(){
var expanders=[];
this.getOpened=function(selected){
angular.forEach(expanders,function(expander){
if(selected!=expander){
expander.showMe=false;
}
});
};
this.addExpander=function(expander){
expanders.push(expander);
};
}
};
})
.directive('expander',function(){
return {
restrict:'E',
replace:true,
transclude:true,
require:"^?accordion",
template:['<div>',
'<div ng-click="toggle()">{{scopeTitle}}</div>',
'<div ng-show="showMe" ng-transclude>{{scopeText}}</div>',
'</div>'].join(''),
scope:{scopeTitle:'=expandTitle',
scopeText:'=expandText',
},
link:function(scope,element,attrs,accordionController){
scope.showMe=false;
accordionController.addExpander(scope);
scope.toggle=function(){
scope.showMe=!scope.showMe;
accordionController.getOpened(scope);
};
}
};
})
.controller('MyController',['$scope',function($scope){
$scope.expanders=[{
title:'click1',
text:'text1'
},{
title:'click2',
text:'text2'
},{
title:'click3',
text:'text3'
}];
}]);

再看HTML:
    <div ng-controller='MyController'>
        <accordion>
            <expander ng-repeat='expander in expanders' expand-title='expander.title' expand-text='expander.text'></expander>
        <accordion>
    </div>
    可以想见,我要实现一个展开就其他收缩的功能,我得有一个地方存储所有expander的状态。尽管在expander的link中的scope可以访问到MyController的scope从而可以找到expanders,但是最好不要这样做,还是隔离的好。那么最好的地方就是在expander的父元素accordion中存储。accordion相当于一个仓库,他提供了API供别人使用。

最新文章

  1. mybatis问题is not known to the MapperRegistry
  2. View与Control间的数据交互
  3. ros科大讯飞语音识别
  4. 各种浏览器css hack
  5. 分享9款极具创意的HTML5/CSS3进度条动画
  6. 委派RODC管理员
  7. 幸运大转盘-jQuery+PHP实现的抽奖程序
  8. javascript 如何正确使用getElementById,getElementsByName(), and getElementsByTagName()
  9. 201521123104 《JAVA程序设计》第二周学习总结
  10. 用.Net Core控制台模拟一个ASP.Net Core的管道模型
  11. vue框架构建项目流程
  12. windows控件理论学习
  13. Select 子句后的别名,在where条件中不能使用
  14. Java实现Windows、Mouse监听器
  15. linux中执行shell命令的几种常用方法
  16. oracle 迁移
  17. 纯HTML和CSS实现JD轮播图
  18. js控制手机端字体大小rem
  19. windows批处理文件打印幻方
  20. 【CODEVS】1022 覆盖

热门文章

  1. Oracle数据库体系结构(1)整体概述
  2. Jooq比较偏的用法
  3. 高性能js之数据访问性能
  4. iOS项目中获取验证码倒计时及闪烁问题解决方案
  5. Fidder工具抓包及篡改数据
  6. Spring Cloud之DiscoveryClient使用
  7. mysql 的类型转换函数cast的用法
  8. TCP/IP 协议中的编址
  9. Oracle的基本操作
  10. 分享知识-快乐自己:Shrio 权限标签