一些常见的错误

  1. 在angularjs里,创建directive时,directive的名称应该要使用驼峰式,例如myDirective,而在html里要调用它的时候,就不能用驼峰式了,可以用my-directive或者my_directive,一般都使用前者吧,统一下规范。
  2. 若声明了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 pass null to the link 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 the link fn if not found.
    • ?^^ - Attempt to locate the required controller by searching the element's parents, or pass
  • null to the link 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的一个渲染过程了:

  1. 浏览器先加载所有的html标识,将其转化为DOM,当浏览器遇到angularjs的时候,就会停止解析过程,去执行angularjs
  2. angularjs在DOM中搜索ng-app执行,若搜索到,则初始化一些必要的组件(即$injector、$compile服务以及$rootScope),然后从该元素开始执行angular的编译
  3. angularjs查看整一棵树,如果发现有directive,则将directive以及它的compile函数一起加入到待编译组里,等全部搜索完毕后,在根据他们的优先级对他们进行依赖注入和编译
  4. 编译运行完后,就会执行它们的链接函数,注册一些监听事件

具体的详情可以去看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学习心得的更多相关文章

  1. angularJS Directive学习

    Directive 指令 直接上实例 index.html <!doctype html> <html ng-app="drag"> <head> ...

  2. AngularJS Directive 学习笔记

    指令 Directive 指令要点 大漠老师的教学节点 解析最简单的指令 hello: 匹配模式 restrict 解析最简单的指令 hello: template.tempmlateUrl.$tem ...

  3. 学习AngularJs:Directive指令用法(完整版)

    这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下   本教程使用AngularJs版本:1.5.3 AngularJs GitHub: http ...

  4. 学习AngularJs:Directive指令用法

    跟我学AngularJs:Directive指令用法解读(上) http://blog.csdn.net/evankaka/article/details/51232895 跟我学AngularJs: ...

  5. Angularjs directive全面解读(1.4.5)

    说到Angularjs directive即指令,可以这么说Angularjs的灵魂就是指令,学会Angularjs指令那么你的Angularjs的武功就修炼了一半了,当然这只是鄙人的一点点独到见解, ...

  6. AngularJs:Directive指令用法

    摘自:http://www.jb51.net/article/83051.htm 摘要:Directive(指令)是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元 ...

  7. 【js类库AngularJs】学习angularJs的指令(包括常见表单验证,隐藏等功能)

    [js类库AngularJs]学习angularJs的指令(包括常见表单验证,隐藏等功能) AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀 ...

  8. 50.AngularJs directive详解及示例代码

    转自:https://www.cnblogs.com/best/tag/Angular/ 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: https://github ...

  9. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

随机推荐

  1. Java条件语句之 switch

    当需要对选项进行等值判断时,使用 switch 语句更加简洁明了.例如:根据考试的名次,给予前 4 名不同的奖品.第一名,奖励笔记本一台:第二名,奖励 IPAD 2 一个:第三名,奖励移动电源一个:最 ...

  2. Shell 的source命令

    source命令用法: source FileName 作用:在当前bash环境下读取并执行FileName中的命令. 注:该命令通常用命令“.”来替代. 如:source .bash_rc 与 . ...

  3. 最新 Arduino 驱动 12接口/户外 LED显示屏/LED点阵屏/LED单元板

    起因 现有的驱动LED显示屏的资料,比较好的只有这个.但是它驱动的是08接口的室内显示屏,而我要驱动的是12接口的户外显示屏.两种屏幕的区别在于户外屏幕点阵比较稀疏,而且二者的扫描方式,驱动方式都不太 ...

  4. suse linux环境变量设置

    以在suse上安装jdk1.5为例说明: 安装jdk1.5完毕后,就可以配置环境变量了. su  root XXXXXX // 键入管理员密码 对于suse来说,只需在/etc/profile 文件后 ...

  5. ASIFormDataRequest 登录

    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: [NSURL URLWithString: @"http: ...

  6. 嵌入式 H264视频通过RTMP直播

    前面的文章中提到了通过RTSP(Real Time Streaming Protocol)的方式来实现视频的直播,但RTSP方式的一个弊端是如果需要支持客户端通过网页来访问,就需要在在页面中嵌入一个A ...

  7. MVC和WebApi 使用get和post 传递参数。

    我们总结一下用js请求服务器的传参方法. Get方式 Get主要是用来查询,一般分为无参,一个参数,多个参数,实体对象参数. 1.无参 //Get没有参数 var get_f1 = function( ...

  8. collect my database for test KCF tracker tools

    Path Button used to set dir where avi file saves, set path set video size and start record write to ...

  9. Anychart 破解备注

    由于项目里用到anychart组件,第一次破解了,后来升级再破解时忘了方法,所以在这里备注一下. 首先需要的工具: swfc  (http://www.buraks.com/swifty/swfc.h ...

  10. java类与对象的动手动脑和其他小问题

    在Java中,我们可以通过组合一私有字段和一对get/set方法来定义一个属性.私有的变量,共有的方法. package sample; /** * 自定义Java类的示例 */ class MyCl ...