详谈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 每当一个指令被创建的时候,都会有这样一个选择,是继承自己的父作用域(一般是外部 ...
随机推荐
- MacOS下搭建python环境
1. 安装须知 Mac OS自身其实已经带有Python,版本为2.7.X,这个Python主要用于支持系统文件和XCode,所以我们在安装新的Python版本时候最好不要影响这部分. 这里就会出现一 ...
- myeclipse和ecplise中安装git插件的问题
我的myeclipse10.7和ecplise helis一直安装不了git插件,myeclipse中details说我的myeclipse少了team_features等之类文件,helis的情况大 ...
- scala程序运行的几种方式
HelloWorld简单实例 object HelloWorld{ def main(args:Array[String]){ println("HelloWorld") } } ...
- 【php】set_include_path和get_include_path用法详解
目的:在框架中方便加载文件 参考:http://blog.sina.com.cn/s/blog_4ce89f200100twbl.html 如果我们没有设置这个值,可能我们需要写一些完全的路径: ...
- TP中if标签
if标签 If标签如果php中if语句的作用,if是用于流程控制的. 在ThinkPHP中if标签也是用于流程控制的. If标签的语法格式: <if condition=’条件表达式’> ...
- 第124天:移动web端-Bootstrap轮播图插件使用
Bootstrap JS插件使用 > 对于Bootstrap的JS插件,我们只需要将文档实例中的代码粘到我们自己的代码中> 然后作出相应的样式调整 Bootstrap中轮播图插件叫作Car ...
- 【bzoj4428】[Nwerc2015]Debugging调试 数论+记忆化搜索
题目描述 一个 $n$ 行的代码出了bug,每行都可能会产生这个bug.你要通过输出调试,在其中加入printf来判断bug出现的位置.运行一次程序的时间为 $r$ ,加入一条printf的时间为 $ ...
- Django 2.0 学习(18):Django 缓存、信号和extra
Django 缓存.信号和extra Django 缓存 由于Django是动态网站,所以每次请求均会去数据库进行相应的操作,当程序访问量大时,耗时必然会显著增加.最简单的解决方法是:使用缓存,缓存将 ...
- "strcmp()" Anyone? UVA - 11732(trie出现的次数)
给你n个单词,让他们两两比较,要求他们运用strcmp时,进行比较的次数. 边建树边统计 #include <iostream> #include <cstdio> #incl ...
- Going in Cycle!! UVA - 11090(二分+判断环路 )
题意: 给定一个n个点m条边的加权有向图,求平均权值最小的回路 解析: 首先肯定是想到找出环路 然后..呵..呵..呵呵... 显然不现实!! 二分大法好 ....去猜结果 然后带入验证 ...真是 ...