angularjs directive学习心得
一些常见的错误
- 在angularjs里,创建directive时,directive的名称应该要使用驼峰式,例如myDirective,而在html里要调用它的时候,就不能用驼峰式了,可以用my-directive或者my_directive,一般都使用前者吧,统一下规范。
- 若声明了compile函数,link函数就不会被调用
transclude
transclude有三个选项,true, false, 和object.如果不显示指明的话,默认为false.
当为false的时候,则那个directive里面的指令不会嵌入到你写的模板里,举个例子
下面是html代码
<div my-directive>
<h1>Hello</h1>
<div>all the content will be erased</div>
</div>
下面是javascript代码
angular.module("app")
.directive("myDirective", function() {
return {
restrict: "A",
template: "<div>This is my template</div>"
}
})
运行结果如下图:
这时候会发现,原来你在div里面写的内容全部不见了,直接被template覆盖了,这就是使用transclude:false的情况,原来那个directive里面的内容都不会嵌入到你写的模板来。
当然,我们可以使用transclude:true来解决这个问题。
只改变原来的directive代码,如下:
.directive("myDirective", function() {
return {
restrict: "A",
transclude: true,
template: "<div>This is my template</div> <div ng-transclude></div>"
}
})
运行结果如下图:
这个时候,原来那个div里面的所有内容都被放置到了ng-transclude声明的那个div里面了。因此只需要把transclude设置为true,然后在你的template里,在你想要原来指令放置在那里的地方,加一个ng-transclude,就可以将其放在里面.
那么,第三个选项object到底是干嘛的呢?还是让我们用一个例子来说明
将之前的html代码修改如下:
<div my-directive>
<transclude-name>CJG</transclude-name>
<transclude-school>SYSU</transclude-school>
<h1>路人甲</h1>
<h2>路人乙</h2>
</div>
以及javascript代码如下:
.directive("myDirective", function() {
return {
restrict: "A",
transclude: {
"name": "?transcludeName",
"school": "?transcludeSchool"
},
template: "<div>This is my template</div> <div ng-transclude></div>" +
"<div ng-transclude='name'></div> <div ng-transclude='school'></div>";
}
})
在这里,我们在html里增加了一些标签,然后在transclude里,给一些标签设置了一些名字,然后我们就可以在template里,让ng-transclude="你设置的名字"来将你某些特定的内容放在特定的位置,当然,你如果直接使用ng-transclude的话,就默认将所有你没有设置名字的标签全部移到里面.(这里在标签名字前面增加一个?号,是为了防止标签不存在而报错)
运行结果如下:
到这里,transclude的几个属性值就已经介绍完了,然而transclude还有一个坑,就是你如果不做特殊处理的话,他会创建一个单独的作用域,与外界分隔开,这就会导致你无法访问到之前的变量,还是让我们来看一个例子.
这里,我们先写了一个controller,里面只有一个$scope.name变量
(function() {
var app = angular.module("app", []);
angular
.module("app")
.controller("myCtrl", function($scope) {
$scope.name = 'CJG';
})
})()
之后,我们在html里,将$scope.name显示出来
<div ng-controller="myCtrl" my-exam>
<h1>my</h1>
<h1>{{name}}</h1>
</div>
然后,我们像之前一样,写一个简单的directive,利用ng-transclude将原来div的内容放到我们指定的区域内
angular.module("app")
.directive("myExam", function($compile) {
return {
restrict: "A",
transclude: true,
template: "<h1>Hello</h1> <div ng-transclude></div>"
}
})
那么,运行结果会不会和我们预期的一样,在ng-transclude里显示两个h1标签呢?让我们来看下
由上图可知,只显示了一个h1,而那个{{name}}没有显示出来,那么他有渲染吗?
由上图可以看到,他是有渲染两个div的,可是为什么就是没有值呢?原因就是因为,你使用transclude的话,默认是会创建一个新的作用域的,因此你就无法访问到之前作用域的值了。那么,怎么解决这个问题呢?
看了很多资料,我觉得比较有用的解决方法是以下两个:
1.使用transclude函数来将解决。transclude的函数原型为: transclude(scope, function(clone){}),我们可以将这个directive的scope传入给他,这样transclude就不会默认产生新的作用域,而是沿用我传给他的那个作用域,当然,你也可以根据自己的需求,传入你想传给他的scope,代码修改如下:
angular.module("app")
.directive("myExam", function($compile) {
return {
restrict: "A",
transclude: true,
template: "<h1>Hello</h1>",
compile: function(elem, attrs, transclude) {
return function(scope, element, attrs) {
transclude(scope, function(clone) {
elem.append(clone);
})
}
}
}
})
运行效果如下:
此时,就可以正常运转了。不过这个必须依赖于complie函数,然后通过他返回的link函数给transclude的内容一个作用域,然后将transclude的内容加载到页面里。
2.这种方法,其实讲道理根本不算用transclude的做法,不过也算是一种方法吧。。。。
angular.module("app")
.directive("myExam", function($compile) {
return {
restrict: "A",
link: function(scope, element, attrs) {
var subScope = scope.$new(true);
var newNode = $compile("<h1>Hello</h1>")(subScope);
element.append(newNode);
}
}
})
其实就是将你要加入的内容在link里面编译,然后用$scope.$new为它创建一个作用域,然后把它加到里面去。(我也不知道这算不算方法)
require
这个参数是用来加载其他directive的controller用的,比如你可能需要到父元素的controller的一些变量或者方法,那么你就可以通过他来访问父元素的controller ,示例如下:
angular.module("app")
.directive("myExam", function($compile) {
return {
restrict: "A",
require: "?^myParent",
link: function(scope, element, attrs, ctrl) {
console.log(ctrl);
ctrl.sayHello();
var subScope = scope.$new(true);
var newNode = $compile("<h1>Hello</h1>")(subScope);
element.append(newNode);
}
}
})
.directive("myParent", function() {
return {
restrict:"A",
controller: function myParent($scope) {
vm = this;
vm.name ="CJG"
vm.sayHello = function() {
console.log("hello");
}
}
}
html代码如下:
<div my-parent>
<div ng-controller="myCtrl" my_exam>
<h1>my</h1>
<h1>{{name}}</h1>
</div>
</div>
在这里,我们在my-exam的directive里引用了他的父亲my-parent的控制器,然后调用了它的方法,运行效果如下:
加?^的前缀是为了防止找不到控制器的时候,报错,让整个程序崩掉,具体的前缀情况如下:
- (no prefix) - Locate the required controller on the current element. Throw an error if not found.
?
- Attempt to locate the required controller or passnull
to thelink
fn if not found.
^
- Locate the required controller by searching the element and its parents. Throw an error if not found.
^^
- Locate the required controller by searching the element's parents. Throw an error if not found.
?^
- Attempt to locate the required controller by searching the element and its parents or pass
null
to thelink
fn if not found.?^^
- Attempt to locate the required controller by searching the element's parents, or pass
null
to thelink
fn if not found.
restrict
restrict有四个选项,"A"(属性值),"E"(元素),"C"(类名),"M"(评论)
比如你将一个声明为E的话,那么你只能通过来调用它,不过一个directive可以声明为多个选项.
template
一个html段
templateUrl
类似于html段,不过就是将它单独写在一个文件里,通过url异步加载进来,compile在它的加载过程中,即使之前使用缓存,它也会去执行别的directive的编译工作,这样就不会导致阻塞。
compile
该函数有三个参数,tElement,tAttrs,transclude,该函数主要用于改变template DOM,而link函数则主要用于注册一些监听事件和执行directive的大多数逻辑.
这个时候就涉及到html的一个渲染过程了:
- 浏览器先加载所有的html标识,将其转化为DOM,当浏览器遇到angularjs的时候,就会停止解析过程,去执行angularjs
- angularjs在DOM中搜索ng-app执行,若搜索到,则初始化一些必要的组件(即$injector、$compile服务以及$rootScope),然后从该元素开始执行angular的编译
- angularjs查看整一棵树,如果发现有directive,则将directive以及它的compile函数一起加入到待编译组里,等全部搜索完毕后,在根据他们的优先级对他们进行依赖注入和编译
- 编译运行完后,就会执行它们的链接函数,注册一些监听事件
具体的详情可以去看https://my.oschina.net/brant/blog/419641,我觉得这篇博客说的很清楚.
link
该函数有5个参数,scope, iElement, iAttrs, controller, transcludeFn
controller我们可以通过之前的require属性传过来。
attrs
directive可以利用attrs来做很多事情,比如,通过attr来访问共同的attribute对象,可以通过$observe来观察attribute值的变化
.directive("myExam", function($compile) {
return {
replace: true,
restrict: "A",
require: "?^myParent",
link: function(scope, element, attrs, ctrl) {
// console.log(ctrl);
ctrl.sayHello();
scope.school = scope.$eval(attrs.ngModel);
var newNode = $compile("<h1>Hello {{ name }} </h1> <h1>school {{ school}}</h1>")(scope);
element.append(newNode);
scope.$watch(
function() {
return scope.$eval(attrs.ngModel);
},
function() {
scope.school = scope.$eval(attrs.ngModel)
})
}
}
})
angularjs directive学习心得的更多相关文章
- angularJS Directive学习
Directive 指令 直接上实例 index.html <!doctype html> <html ng-app="drag"> <head> ...
- AngularJS Directive 学习笔记
指令 Directive 指令要点 大漠老师的教学节点 解析最简单的指令 hello: 匹配模式 restrict 解析最简单的指令 hello: template.tempmlateUrl.$tem ...
- 学习AngularJs:Directive指令用法(完整版)
这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: http ...
- 学习AngularJs:Directive指令用法
跟我学AngularJs:Directive指令用法解读(上) http://blog.csdn.net/evankaka/article/details/51232895 跟我学AngularJs: ...
- Angularjs directive全面解读(1.4.5)
说到Angularjs directive即指令,可以这么说Angularjs的灵魂就是指令,学会Angularjs指令那么你的Angularjs的武功就修炼了一半了,当然这只是鄙人的一点点独到见解, ...
- AngularJs:Directive指令用法
摘自:http://www.jb51.net/article/83051.htm 摘要:Directive(指令)是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元 ...
- 【js类库AngularJs】学习angularJs的指令(包括常见表单验证,隐藏等功能)
[js类库AngularJs]学习angularJs的指令(包括常见表单验证,隐藏等功能) AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀 ...
- 50.AngularJs directive详解及示例代码
转自:https://www.cnblogs.com/best/tag/Angular/ 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: https://github ...
- 我的MYSQL学习心得(一) 简单语法
我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
随机推荐
- 2016第20周四java基础概念
简单的说JDK=JRE+Java编译器.调试器.工具类库等:JRE=JVM(类似于jre目录下的bin)+必要运行的类库(类似于jre目录下的lib) JVM:Java Virtual Mechina ...
- FontMetrics ----- 绘制文本,获取文本高度
Canvas 绘制文本时,使用FontMetrics对象,计算位置的坐标. public static class FontMetrics { /** * The maximum distance a ...
- (转)Visual Studio原生开发的10个调试技巧(二)
我以前关于Visual Studio调试技巧的文章引起了大家很大的兴趣,以至于我决定分享更多调试的知识.以下的列表中你可以看到写原生开发的调试技巧(接着以前的文章来编号).这些技巧可以应用在VS200 ...
- GC Buffer Busy Waits处理(转载)
与单实例不同,在RAC环境中,由于多节点的原因,会因为节点间的资源争用产生GC类的等待,而这其中,GC Buffer Busy Waits又是最为常见的,从性能角度上说,RAC是把双刃剑,用的好,能够 ...
- 【LR】OSGI性能测试实例
其实我们就两点Ø 确定测试登录最大并发用户数:Ø 事务平均响应时间 (两个查询) 得到这个任务 如何展开测试工作呢? 一.WindowsResources 设置(其实不监控 设不设都行 我感觉) ...
- [转]Linux文件和目录操作命令
转自:http://www.linuxdiyf.com/bbs/thread-416176-1-1.html 一.文件操作命令1.1 查看文件 Linux下查看文件的命令有很多,下面列出的几个是几乎所 ...
- Linux 下部署单机 hadoop 测试
最终运行结果展示: 格式化namenode. 开始测试 显示测试进程 浏览器查看效果展示:(虽然还不清楚是什么意思,但是能看到这个效果已经很开心了) 话不多说,进入主题: 1. 安装 VMwareSt ...
- 关于python中的__new__方法
在上篇中,简单的比较了下new方法和init方法,然后结合网上的东西看了一点,发现..看书有的时候说的并不全面. __new__方法是一个类方法,主要作用是来指导如何生成类的实例, 主要用于,当需要生 ...
- dispatch_once单例初始化
static GHCache *instance = nil; /** * 单例,静态初始化方法 * * @return 返回一个单例 */ + (GHCache*)shareCache{ sta ...
- Spring3 整合Quartz2 实现定时任务
一.Quartz简介 Quartz是一个由James House创立的开源项目,是一个功能强大的作业调度工具,可以计划的执行任务,定时.循环或在某一个时间来执行我们需要做的事,这可以给我们工作上带来很 ...