angularJS系列之指令directive应用实例
2016-07-08 11:50
507 查看
代码结构
html页面代码
<!DOCTYPE html> <html ng-app="demoForDirective"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <script src="./lib/angular.js"></script> <script src="./js/app.js"></script> <script src="./js/controller.js"></script> </head> <body> <div ng-controller='demoForDirectiveController'> <!--增加指令标签--> <testdirective testdirective-title='title'> {{text}} </testdirective> </div> <div> <!--为原生标签增加动态属性--> 分数:<input type="text" attrsdirective/><br/> </div> <!--通过控制器控制子元素--> <div ng-controller="SomeController"> <accordion> <expander class="expander" ng-repeat="expander in expanders" expander-title="expander.title"> {{expander.text}} </expander> </accordion> </div> </body> </html>
app.js代码
/** * Created by jywl on 2016/7/7. */ var demoForDirective = angular.module('demoForDirective', ['demoForDirective.controller']); demoForDirective.directive('testdirective', function () { return { restrict: 'EA', replace: true, transclude: true, scope: { title: '=testdirectiveTitle' }, template: '<div>' + '<div class="title" ng-click="toggle()">{{title}}</div>' + '<div class="body" ng-show="showMe" ng-transclude></div>' + '</div>', link: function (scope, element, attrs) { scope.showMe = false; scope.toggle = function toggle() { scope.showMe = !scope.showMe; } } } }); demoForDirective.directive('attrsdirective', function () { return { link: function (scope, elements, attrs, controller) { elements[0].onkeyup = function () { //从元素列表中获取元素,并绑定相应的事件 //下面的意思是,如果输入10以内的数,则输入框边框颜色不变,否则变为红色 if (isNaN(this.value) || this.value < 1 || this.value > 10) { this.style.borderColor = 'red'; } else { this.style.borderColor = ''; } }; } } }); demoForDirective.directive('accordion', function () { return { restrict: 'EA', replace: true, transclude: true, template: '<div ng-transclude></div>', controller: function () { //声明一个内部的controller,用于传递值和方法 var expanders = []; this.gotOpened = function (selectedExpander) { //angularJS的forEach用法 /*var objs =[{a:1},{a:2}]; angular.forEach(objs, function(data,index,array){ //data等价于array[index] console.log(data.a+'='+array[index].a); }); 参数如下: objs:需要遍历的集合 data:遍历时当前的数据 index:遍历时当前索引 array:需要遍历的集合,每次遍历时都会把objs原样的传一次。 * */ angular.forEach(expanders, function (expander) { if (selectedExpander != expander) { expander.showMe = false; } }); } this.addExpander = function (expander) { expanders.push(expander); } } } }); demoForDirective.directive('expander', function () { return { restrict: 'EA', replace: true, transclude: true, require: '^?accordion',//意思是将accordion的控制器传到指令中,从而在下方使用它的函数 ^的意思是需要遍历dom树,?的意思是找不到不报错 scope: { title: '=expanderTitle' }, template: '<div>' + '<div class="title" ng-click="toggle()">{{title}}</div>' + '<div class="body" ng-show="showMe" ng-transclude></div>' + '</div>', link: function (scope, element, attrs, accordionController) { scope.showMe = false; accordionController.addExpander(scope); scope.toggle = function toggle() { scope.showMe = !scope.showMe; accordionController.gotOpened(scope); } } } });
controller.js代码
/** * Created by jywl on 2016/7/7. */ angular.module('demoForDirective.controller', []) .controller('demoForDirectiveController', function ($scope) { $scope.title = '点击展开'; $scope.text = '这里是内部的内容。'; }) .controller('SomeController', function ($scope) { $scope.expanders = [ {title: 'click me', text: 'one click'}, {title: 'click me two', text: 'two click'}, {title: 'click me three', text: 'three click'}]; });
代码说明
主要详解app.js中关于指令的代码,大部分代码都有注释,如果还有不清楚的可以留言,我看到会及时回复的。directive的参数说明
priority(优先级)- 当有多个directive定义在同一个DOM元素时,有时需要明确它们的执行顺序。这属性用于在directive的compile function调用之前进行排序。如果优先级相同,则执行顺序是不确定的(经初步试验,优先级高的先执行,同级时按照类似栈的“后绑定先执行”。另外,测试时有点不小心,在定义directive的时候,两次定义了一个相同名称的directive,但执行结果发现,两个compile或者link function都会执行)。据官方说,ng-repeate的优先级是1000。该属性默认值为0。terminal(最后一组)- 如果设置为”true”,则表示当前的priority将会成为最后一组执行的directive。任何directive与当前的优先级相同的话,他们依然会执行,但顺序是不确定的(虽然顺序不确定,但基本上与priority的顺序一致。当前优先级执行完毕后,更低优先级的将不会再执行)。
scope - 如果设置为:
true - 将为这个directive创建一个新的scope作用域,而不是继承父作用域。
false - 默认值,使用现有的scope作用域。
{/属性名和绑定风格/} - 独立的scope。
独立scope与一般的scope的区别在于它不是通过原型继承于父scope的。这对于创建可复用的组件是很有帮助的,可以有效防止读取或者修改父级scope的数据。
绑定策略
@或@attr - 建立一个local scope property到DOM属性的绑定。因为属性值总是String类型,所以这个值总是返回一个字符串。如果没有通过@attr指定属性名称,那么本地名称将与DOM属性的名称一致。例如
<widget my-attr=”hello {{name}}”>,widget的scope定义为:
{localName:’@myAttr’}。那么,widget scope property的localName会映射出”hello {{name}}”转换后的真实值。name属性值改变后,widget scope的localName属性也会相应地改变(仅仅单向,与下面的”=”不同)。name属性是在父scope读取的。
=或=expression(绑定当前属性,它带来一个来自指令父scope的属性) - 在本地scope属性与parent scope属性之间设置双向的绑定。如果没有指定attr名称,那么本地名称将与属性名称一致。例如,widget定义的scope为:{localModel:’=myAttr’},那么widget scope property “localName”将会映射父scope的“parentModel”。如果parentModel发生任何改变,localModel也会发生改变,反之亦然。(双向绑定)
&或&attr - 传递一个来自父scope的函数,稍后调用。
controller - controller 构造函数。controller会在pre-linking步骤之前进行初始化,并允许其他directive通过指定名称的require进行共享(看下面的require属性)。这将允许directive之间相互沟通,增强相互之间的行为。
controller默认注入了以下本地对象:
$scope - 与当前元素结合的scope
$element - 当前的元素
$attrs - 当前元素的属性对象
$transclude - (A transclude linking function pre-bound to the correct transclusion scope)
require - 请求另外的controller,传入当前directive的linking function中。require需要传入一个directive controller的名称。如果找不到这个名称对应的controller,那么将会抛出一个error。名称可以加入以下前缀:
? - 不要抛出异常。这使这个依赖变为一个可选项。
^ - 允许查找父元素的controller
restrict - EACM的子集的字符串,它限制directive为指定的声明方式。如果省略的话,directive将仅仅允许通过属性声明:
E - 元素名称:
<my-directive></my-directive>
A - 属性名:
<div my-directive=”exp”></div>
C - class名:
<div class=”my-directive:exp;”></div>
M - 注释 :
<!-- directive: my-directive exp -->
template - 如果replace 为true,则将模版内容替换当前的HTML元素,并将原来元素的属性、class一并迁移;如果为false,则将模版元素当作当前元素的子元素处理。
templateUrl - 与template基本一致,但模版通过指定的url进行加载。因为模版加载是异步的,所以compilation、linking都会暂停,等待加载完毕后再执行。
replace - 如果设置为true,那么模版将会替换当前元素,而不是作为子元素添加到当前元素中。(注:为true时,模版必须有一个根节点)
transclude - 编译元素的内容,使它能够被directive所用。(如果当前元素,希望其他directive调用,就将其设为true,并在元素的节点上,增加
<div ng-transclude></div>就好,更高级的用法,目前我还在学习中)
true - 转换这个directive的内容。(这个感觉上,是直接将内容编译后搬入指定地方)
element - 转换整个元素,包括其他优先级较低的directive。(像将整体内容编译后,当作一个整体(外面再包裹p),插入到指定地方)
compile - 编译函数,整个运行周期中只执行一遍。(一般情况下,用compile即可。)
link - 链接函数,可以多次执行。具体用法参照上文代码
相关文章推荐
- Angularjs 跨域请求
- 在Windows 8.1的IE 11中屏蔽双击放大功能
- HTML5调用摄像头实例
- Powershell 创建炫丽美观的Html报表
- Apple官网研究之使用Justify布局导航
- 关于前端的思考与感悟
- 又被事件冒泡坑了一把,这次要彻底弄懂浏览器的事件流
- 移动端点击事件全攻略,这里的坑你知多少?
- $q 实例分析 Angular 中的 Promise
- Angular directive 实例详解
- 关于浮动与清除浮动,你应该知道的
- 通过Mootools 1.2来操纵HTML DOM元素
- jQuery Html控件基本操作(日常收集整理)
- WEB标准网页布局中尽量不要使用的HTML标签
- Flash 与 html 的一些实用技巧
- html工作中表格<tbody>标签的使用技巧
- HTML 向 XHTML1.0 兼容性指导
- C#自写的一个HTML解析类(类似XElement语法)