详谈AngularJS的Directive
指令Directive是AngularJS最重要的核心。我用AngularJS用的并不是很深,一直以来也是在使用中摸索,从一开始的什么都不懂,查不到系统的资料,到开始使用一些简单的数据绑定{{}},到发现ng-bind比双括弧好用是因为DOM加载速度的问题,到发现简单的ng-repeat能完成很多事情,到用它来做表单验证时发现ng-form好好用,到... 总之,对AngularJS从无知到有一定认可的现在,我觉得我使用它最大的好处就是数据绑定,将数据绑定在$scope里面然后想怎么写就怎么写。除此之外,使用AngularJS也让我慢慢理解组件化开发的概念,我也越来越倾向于使用这样的方式去开发,更加赞同这样的理念。
然而直到目前为止,我仍然停留在使用一些简单的数据绑定的层次中,虽然数据绑定是angularJS的一大核心,但是如果不掌握Directive,实现自己的依赖注入,是不能完全发挥出AngularJS的功效的,AngularJS最终的功效是自定义的模块化组件式开发,这里面的自定义,就是由Directive来实现的,所以,我觉得有必要专门用一篇博客来记录我对Directive的学习过程。
什么是指令?
我对指令的肤浅理解就是我们用的HTML标签,我们平时写一些原生HTML经常会发现满足不了需求,所谓自定义指令其实可以理解为自定义标签。据我现在的manager说他以前在一个上十个人的team中,一个项目下来得有上百个directive。那么我的理解是,directive,从标签的角度上来说封装了原生的HTML,从数据的角度上来说实现了数据绑定并且封装了ajax,它让一个自定义的标签有了集成的HTML功能,并且可以和动态的数据进行交互。可能还没有理解到位,可能还没有完全体会到Directive的精妙,但是怎么说呢?我目前就能够用到这些,简单的东西对我的帮助也是巨大的,从现实的角度上来说,用不上的,就是没有用的,从项目的角度上来讲,要从需求出发,而不应该从技术难度出发,先用起来再去学习,能用多少学多少,用完了再把剩下的想学多少学多少,而不是先学完了再去用。
上面说的还比较复杂,举个简单的例子吧,我们以前经常这样写HTML
<div>
<span>一点点内容</span>
</div>
现在我们可以这么写了
<tabpanel>
<panel>子面板1</panel>
<panel>子面板2</panel>
</tabpanel>
这样写肯定会有问题,因为当浏览器看到这些标签的时候,它心里肯定会想,这是什么鬼?不过在你用directive对这些标签做过解释之后,浏览器就能认得它们了,这就是Directive。
Hello,World!
这是我刚开始学习AngularJS的时候看到的一个Directive的示例,我喜欢简洁的Test风格的代码,就像"Hello,World!"那样,不管学什么东西,先尝试着对这个东西say hello,先用它来说话,我觉得这是一种很好的习惯。
module.directive( "directive_name", [ 'JSONObject', function( JSONObject ) {
return {
restrict: "A",
link: function(scope , element , attrs) {
element.bind( "click", function() {
//directive code
});
}
}
}]);
我至今还没有搞清楚这个JSONObject是怎么个道理注入到directive的function作为参数的,虽然我不知道,但是这貌似不重要,因为我还见过这样的形式:
app.directive('autocomplete', function () {
return {
restrict: 'EA',
replace : true,
transclude : true,
template: autocompleteTpl,
link: function (scope, element, attr) {
}
}
});
化繁为简以后我们就可以更加专注于那些本应该是最开始的事情上了。很显然,这段代码的主体部分是return的返回值,它返回了一个Object,我并不能知道这些键值对是什么,我打算去了解它,而且,感觉没什么用的我暂时不去理会,我没有义务去把一个框架的参数表给背下来,东西是用出来的,不是记出来的,更何况是别人写的框架,别人的东西。
好吧!它还不是最简单的,最简单的应该是这个样子的
var appModule = angular.module('app', []);
appModule.directive('hello', function() {
return {
restrict: 'E',
template: '<div>Hi there</div>',
replace: true
};
});
先说下restrict,它说明了我们的指令的类型,一共有4种,E是Element,A是Attribute,C是Class,M是Comment,一看就明白,看不明白还可以看图

注意一下,我们一般不用后两种,就是C和M,不用C的主要原因是因为MVC的思维,尽可能地不要让JS代码污染CSS。
template是我们要替换指令的内容,就是HTML的模板。
replace控制了替换的开关,当它为false的时候,template不会去替换指令,我们一般设置成true。
Transclude
如果我们需要替换的HTML标签很长,显然不能用 拼接字符串的方式来写,这时候我们可以用templateUrl来替代template,从而可以把模板写到一个独立的HTML文件中。
var appModule = angular.module('app', []);
appModule.directive('hello', function() {
return {
restrict: 'E',
template: '<div>Hi there <span ng-transclude></span></div>',
transclude: true
};
});
transclude的作用是用我们规定的template去替换我们自定义的指令标签并且template内部的结构(子标签)保持不变。
Compile&Link
当我们需要把某些事情绑定到某个元素上,我们就需要提供一个link函数
var expanderModule=angular.module('expanderModule', [])
expanderModule.directive('expander', function() {
return {
restrict : 'EA',
replace : true,
transclude : true,
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) {
scope.showMe = false;
scope.toggle = function toggle() {
scope.showMe = !scope.showMe;
}
}
}
});
expanderModule.controller('SomeController',function($scope) {
$scope.title = '点击展开';
$scope.text = '这里是内部的内容。';
});
HTML
<html ng-app='expanderModule'>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="angular.min.js"></script>
<link rel="stylesheet" type="text/css" href="ExpanderSimple.css"/>
</head>
<body>
<div ng-controller='SomeController'>
<expander class='expander' expander-title='title'>
{{text}}
</expander>
</div>
</body>
<script src="ExpanderSimple.js"></script>
</html>
Template可以是一个函数
这个函数可以接收两个参数,一个是tElements,一个是tAttrs
其中tElement是指使用此指令的元素,而tAttrs则实例的属性,它是一个由元素上所有的属性组成的集合(对象)形如
{title:'title', name:'Larry'}
当template是一个函数的时候
angular.module("app",[]).directive("directitle",function(){
return{
restrict:'EAC',
template: function(tElement,tAttrs){
var _html = '';
_html += '<div>'+tAttrs.title+'</div>';
return _html;
}
};
})
这个时候我们可以在HTML里愉快的设置属性,结果就会有对应的变化,比如这样
<directitle title='hello'></directitle>
结果就会变成
<div>hello</div>
===============2016年3月1日================
1.restrict
E: 表示该directive仅能以element方式使用,即:<my-dialog></my-dialog>
A: 表示该directive仅能以attribute方式使用,即:<div my-dialog></div>
EA: 表示该directive既能以element方式使用,也能以attribute方式使用
2.transclude
你的directive可能接受页面上的其他html内容时才会用到,建议先去掉该参数。有些高阶了。
3.scope
当你写上该属性时,就表示这个directive不会从它的controller里继承$scope对象,而是会重新创建一个。
4.templateUrl
你的directive里的html内容
5.link
可以简单理解为,当directive被angular 编译后,执行该方法
element简单说就是$('directive')
attrs是个map,内容是你这个directive上的所有属性,假如在页面上这样写一个directive:
<my-dialog type="modal" animation="fade"></my-dialog>
那attrs就是:
{
type: 'modal',
animation: 'fade'
}
文章来源:
http://damoqiongqiu.iteye.com/blog/1917971
http://my.oschina.net/ilivebox/blog/289670
详谈AngularJS的Directive的更多相关文章
- AngularJS之directive
AngularJS之directive AngularJS是什么就不多舌了,这里简单介绍下directive.内容基本上是读书笔记,所以如果你看过<AngularJS up and runnin ...
- Angularjs之directive指令学习笔记(二)
1.Directive的五个实例知道driective作用.其中字段restrict.template. replace.transclude.link用法 参考文章链接地址:http://damoq ...
- 前端angularJS利用directive实现移动端自定义软键盘的方法
最近公司项目的需求上要求我们iPad项目上一些需要输入数字的地方用我们自定义的软键盘而不是移动端设备自带的键盘,刚接到需求有点懵,因为之前没有做过,后来理了一下思路发现这东西也就那样.先看一下实现之后 ...
- Angularjs的directive封装ztree
一般我们做web开发都会用到树,恰好ztree为我们提供了多种风格的树插件. 接下来就看看怎么用Angularjs的directive封装ztree <!DOCTYPE html> < ...
- angularJS中directive父子组件的数据交互
angularJS中directive父子组件的数据交互 1. 使用共享 scope 的时候,可以直接从父 scope 中共享属性.使用隔离 scope 的时候,无法从父 scope 中共享属性.在 ...
- angularJS中directive与directive 之间的通信
上一篇讲了directive与controller之间的通信:但是我们directive与directive之间的通信呢? 当我们两个directive嵌套使用的时候怎么保证子directive不会被 ...
- angularJS中directive与controller之间的通信
当我们在angularJS中自定义了directive之后需要和controller进行通讯的时候,是怎么样进行通讯呢? 这里介绍3种angular自定义directive与controller通信的 ...
- AngularJS之Directive,scope,$parse
AngularJS内幕详解之 Directive AngularJS内幕详解之 Scope AngularJS的指令(Directive) compile和link的区别及使用示例 浅谈Angular ...
- AngularJS中Directive指令系列 - scope属性的使用
文章是转的,我做下补充.原文地址:https://segmentfault.com/a/1190000002773689 每当一个指令被创建的时候,都会有这样一个选择,是继承自己的父作用域(一般是外部 ...
随机推荐
- PyCharm如何设置源代码字体的大小
改源代码大小 1.File→Settings→Editor→Colors&Fonts→Font 2.首先得需要Save as一个Scheme,接下来才可以修改字体,名字可以任意取 改运行字体的 ...
- struts2 jsp的session取值 if判断
model有个类user,其中有个string属性direction(方向) 在LoginAction中 登入成功 就 ActionContext actionContext = ActionCont ...
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
参考 有空再更新下用c++, 下面用的Java Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径 ...
- 简易四则运算生成程序——添加GUI支持
项目成员:张金生 张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...
- PHP上传文件限制的大小
修改PHP上传文件大小限制的方法 1. 一般的文件上传,除非文件很小.就像一个5M的文件,很可能要超过一分钟才能上传完.但在php中,默认的该页最久执行时间为 30 秒.就是说超过30秒,该脚本就停止 ...
- C# 事件总线 EventBus
1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需 ...
- C++解析(17):操作符重载
0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...
- 洛谷P1345 [USACO5.4]奶牛的电信(最小割)
题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...
- Golden Tiger Claw UVA - 11383(km原理)
这题使我对km多了一些看法 写给自己看.. km结束后bx[i] + by[j] == w[i][j], 所以所有bx与by的和即为w的和 而且记住bx[i] + by[j] >= w[i][j ...
- Android ActionBar 使用详解
ActionBar取代了以前的TitleBar,是一种更加灵活的人机交互方式:ActionBar并不是完全自立门户的一个新兴的东西,而是和3.0以下版本的menu进行了合并整合:so,添加action ...