angular中的compile和link函数
angular中的compile和link函数
前言
这篇文章,我们将通过一个实例来了解 Angular 的 directives (指令)是如何处理的。Angular 是如何在 HTML 中找到这些 directive 的。以及如何编写自定义的指令。
这是原文提供的代码:http://www.angularjshub.com/examples/customdirectives/compilelinkfunctions/#top
更加友好的排版:http://blog.wangtuyao.com/post/2014/7/2/compile-and-link-function-in-angular
Initialization, compilation 和 linking 阶段
当 Angular 从 HTML 中解析 directive 的时候,我们每个 directive 的解析可以大致分为 3 步。
initialization :这个阶段是 Angular 在 DOM 遍历的时候第一次发现 directive 的时候执行。(它只会发生一次,即便是在 DOM 中出现了多次)initialization 允许 directive 做一些初始化的工作。
compilation :这个阶段 Angular 遍历 DOM ,并且收集所有的 directive 。所有 directive 都可以在这个阶段操作 DOM(在这个阶段,同一个 directive 在不同的 DOM 节点如果中出现了多次,compilation 将会执行多次)这个阶段 scope 是还没有被附加上去,所以是无法访问到 scope 的。
linking :这个阶段的 DOM 节点,Angular 会把所有 directive 的事件监听器(event listeners)注册到 DOM 中,建立对 scope 的监听。并且把一个 scope 附加到 directive 中。这整个阶段是在 compilation 之后进行的。如果想要访问 scope 就可以在这个阶段进行。
创建自定义 directive
我们可以通过 Angular 中提供的 directive 创建自定义的指令。
directive(name, directiveFactory);
方法提供了两个参数,第一个为 directive 的名字,第二个是一个工厂方法。
在 HTML 中指定来引用一个指令有多种方法,查看更多内容。directive 的命名说有几种约定的规则:
使用驼峰式命名,首字母小写。
HTML 中使用小写字符加横线的方式。
例如:directive 的名称为 myCustomDir 所有 HTML 中引用为 my-custom-dir;
Compile 和 link function
上文讲了 initialization, compilation 和 linking 阶段,现在来看一下 directive 是如何执行的。这是一个最为复杂的例子,这个例子包含了 directive 处理的所有阶段。
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Definition object
return {
// Compile function
compile: function (element, attrs)
{
// ...
return {
// Pre-link function
pre: function (scope, element, attrs)
{
// ...
},
// Post-link function
post: function (scope, element, attrs)
{
// ...
}
};
}
};
});
第一个参数表示 directive 的名字,第二个参数表示 directive 的工厂方法,返回一个对象。这个对象可以包含多个属性,查看更多。这里我们只关注compile 属性。compile 对应了一个 compile function ,这个方法返回一个包含 pre 和 post 属性的对象。为了能更好的理解情况下图:
假如我们定义了如下的自定义的 directive dir1,dir2,dir3 和 dir4 ,Angular 又是如何处理的呢
<... dir1 ...>
<... dir2 dir3 ...>
<... dir4 dir1 ...>
</...>
</...>
</...>
initialization 和 compilation 阶段将会在第一次遍历 DOM 的时候发生。这里是处理过程:
DOM 第一次遍历的时候,dir1 将会首先被发现。所以 dir1 的 initialization 将会首先执行,紧接着的是 dir1 的 compilation 。
在第一个 DOM node 处理完后,接着会处理这个 node 的子 node,这里就是 dir2 , dir3;dir2 和 dir3 是 DOM 第一次遍历到,所以initialization 部分和 compilation 部分会依次调用;
接下来处理 dir2 和 dir3 的子 node,这里包含了 dir4 和 dir1 。因为 dir1 在第一步的时候已经 initialization 过,所以不会再次执行,但是 dir4 还是会调用 initialization 因为它是 DOM 第一次遍历到。所有的 directive 都会在 initialization 后调用 compilation。
如果 html 中还有其他的 DOM 树,处理过程也是类似的,以同样的方式从上到下遍历 DOM 树,如果有 DOM 节点存在着子节点,每个字节点都将会被依次遍历后再进入下一个节点。这个过程结束之后,initialization 和 compilation 的处理也结束了。directive 将会被替换,最终版本的 DOM 树将会呈现出来。
接下来的处理过程是 linking。这个过程有可以细分为 pre-linking 和 post-linking。由于 Angular 使用 depth-first 方式遍历 DOM 树。所以 angular 首先访问到的是 pre-linking ,当所有 pre-linking 执行完毕后,DOM 遍历进入到一个“回溯”(backtracking )阶段的时候所有的 post-linking 才执行。在 pre-linking 函数做DOM 的转换时不安全的(pre-linking 的执行是在节点的子节点还未执行link,意思是:在某一个节点执行 pre-linking 的时候,这个节点的子节点还未进行 link),在post-linking 阶段才是安全的。
自定义指令申明 compile 和 link 函数的几种方式
上文,我们已经知道了一种方式在一个模块中创建一个指令,并且这是一种最复杂的方式,因为我们既需要访问 compile ,pre-link,和 post-link,但是通常情况下我们不需要全部,我们可以根据需求选择不同的函数。我们开看一下几种方式(代码请看上面的链接):
1.不定义对象
我们可以简单的 Post-link 后,不定义对象返回。这是在例 1. 所示。
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Post-link function
return function (scope, element, attrs)
{
// ...
};
});
2.定义一个对象和只定义一个 post-link 函数
定义对象后返回 post-link 函数,如例 2.所示:
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Definition object
return {
// Post-link function
link: function (scope, element, attrs)
{
// ...
}
};
});
3.定义一个对象和定义 post-klink 和 pre-link
返回一个对象,这个对象有一个 link属性,这个 link 属性又包含一个 pre 和 post 属性的对象,分别对应 pre-link 函数和 post-link 函数。如实例 3.所示:
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Definition object
return {
link: {
// Pre-link function
pre: function (scope, element, attrs)
{
// ...
},
// Post-link function
post: function (scope, element, attrs)
{
// ...
}
}
};
});
4.定义一个对象和只定义 compile 函数
返回一个对象,包含 compile 属性,对应 compile 函数,如例 4. 所示:
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Definition object
return {
// Compile function
compile: function (element, attrs)
{
// ...
}
};
});
5.定义一个对象和定义 compile 和 post-link 函数
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Definition object
return {
// Compile function
compile: function (element, attrs)
{
// ...
// Post-link function
return function (scope, element, attrs)
{
// ...
};
}
};
});
6.定义一个对象和 compile,pre-link 和 post-link 函数
最后一种方式,如例 6.所示
myModule.directive("myCustomDir", function ()
{
// Initialization
// ...
// Definition object
return {
// Compile function
compile: function (element, attrs)
{
// ...
return {
// Pre-link function
pre: function (scope, element, attrs)
{
// ...
},
// Post-link function
post: function (scope, element, attrs)
{
// ...
}
};
}
};
});
前一篇博文中的代码作为一个完整的directive示例:
angular.module('demo', [])
.controller('demoController',['$scope',function($scpoe){
$scpoe.rating=52;
}])
.directive('rnStepper', function() {
return {
restrict: 'AE',
require:'ngModel',/*使用属性模式调用,依赖了ngModel指令*/
scope:{},
template: '<button ng-click="decrement()">-</button>' +
'<div></div>' +
'<button ng-click="increment()">+</button>',
//link函数可以接受require指令的controller,ngModelController
link:function(scope,element,attrs,ngModelController){
//利用ngModel指令的controller我们可以利用他的方法很多事情
ngModelController.$render=function(){
element.find('div').text(ngModelController.$viewValue);
};
function updateModel(offset){
ngModelController.$setViewValue(ngModelController.$viewValue+offset);
ngModelController.$render();
};
scope.decrement=function(){
updateModel(-1);
};
scope.increment=function(){
updateModel(1);
};
}
};
});
compile 和 link 的参数
我们已经了解了在自定义指令中定义 compile 和 link 函数。现在来看一下 compile 和 link 的参数。
Angular 使用了一种内置的、轻量级的 jQuery,称为 jqLite 来操作和查询 DOM。但如果页面中同时有 jQuery 存在,那么 Angular 会用 jQuery 替换掉内置的 jqLite。
compile 函数的签名如下:
function (element, attrs)
element : 表示被编译后的、包含了 DOM 节点的 jqLite\jQuery 对象(如:如果 directive 是一个 div 元素,那么 element 是一个 jqLite\jQuery 包装的对象)。
attrs: attrs 是一个对象。这个对象的每一个属性代表着 Node 中的每一个同名属性。(如:Node 中有一个 my-attribute 属性,那么就可以通过 attrs.myAttribute 来获取该属性的值)
link 函数的签名如下:
function (scope, element, attrs)
scope: directive 的 scope;
element: 和 compile 函数的 element 参数相同;
attrs: 和 compile 函数中的 attrs 参数相同
Reference
http://www.angularjshub.com/examples/customdirectives/compilelinkfunctions/
http://www.cnblogs.com/wangtuyao/p/compile-and-link-function-in-angular.html
http://blog.wangtuyao.com
angular中的compile和link函数的更多相关文章
- 【转】angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- angularjs指令中的compile与link函数详解(转)
http://www.jb51.net/article/58229.htm 通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link, ...
- angularjs指令中的compile与link函数详解补充
通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link,post-link的用法与区别. angularjs里的指令非常神奇,允许你 ...
- [译]ng指令中的compile与link函数解析 转
通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link,post-link的用法与区别. 原文地址 angularjs里的指令非常神 ...
- 必须正确理解的---ng指令中的compile与link函数解析
这个绝对是深入的知识,但看完之后,对NG的理解就很利害啦. http://www.ifeenan.com/angularjs/2014-09-04-%5B%E8%AF%91%5DNG%E6%8C%87 ...
- angular.js中指令compile与link原理剖析
在angularJs应用启动之前,它们是以HTML文本形式存在文本编辑器当中.应用启动会进行编译和链接,作用域会同HTML进行绑定.这个过程包含了两个阶段! 编译阶段 在编译的阶段,angularJs ...
- 在Angular中使用$ compile
转载自:http://odetocode.com/blogs/scott/archive/2014/05/07/using-compile-in-angular.aspx 在AngularJS中创建一 ...
- angular学习笔记(三十)-指令(7)-compile和link(2)
继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...
随机推荐
- 1、Spring In Action 4th笔记(1)
Spring In Action 4th笔记(1) 2016-12-28 1.Spring是一个框架,致力于减轻JEE的开发,它有4个特点: 1.1 基于POJO(Plain Ordinary Jav ...
- [资料分享]SQL Server 2016/2014/2012/2008简体中文企业版下载+对应补丁
为什么只提供企业版下载呢?因为不管你是学生还是工作研究人员,企业版都是功能最为齐全的一个版本,比如企业版都集成了SQL Server Management Studio管理界面(俗称企业管理器的可视化 ...
- HTML5 与 CSS3 jQuery部分知识总结
一. HTML5 为什么需要HTML5 什么是HTML5 HTML5现状及浏览器支持 HTML5优点与缺点 HTML5语法规则与文档声明 HTML5新增表达标签 HTML5多媒体组件 HTML5 ...
- AMD与CMD(转载)
JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题 ...
- 案例1.通过Jquery来处理复选框
实现以下功能: 1:选中第一个复选框,那么下面所有的复选框都选中,去除选中第一个复选框,下面的都不选中 2:当点击全选按钮,上面足球.篮球.游泳.唱歌 全部选中 3:当点击全不选按钮,上面四个全部取消 ...
- Node.js抓取网页
前几天四六级成绩出来(然而我没考),用Node.js做了一个模拟表单提交并抓取数据的Web 总结一下用到的知识,简单的网页抓取大概就是这个流程了 发送Get或Post请求 表单提交,首先弄到原网页提交 ...
- -[NSNull countByEnumeratingWithState:objects:count:]:
当数组为空时遍历数组容易出这样的问题, -[NSNull countByEnumeratingWithState:objects:count:]: unrecognized selector sent ...
- Android屏幕适配笔记
1.限定符 为了适配不同屏幕大小的android手机或android平板,有时候就需要利用限定符来为不同的屏幕设定不同的布局文件,在一般情况下我们都是在layout文件夹下为某个活动准备一个默认的布局 ...
- 对象的this引用
Java中的this关键字总是指向调用该方法的对象.根据this出现位置的不同,this作为对象的默认引用有两个功能: 1.构造器中引用该构造器正在初始化的对象. 2.在方法中引用调用该方法的对象. ...
- ArcGIS10的附件功能
转自 积思园 http://blog.csdn.net/linghe301/article/details/6386176 老是忘记怎么使用这个ArcGIS10的附件功能,这次就做个记录吧. 在项目应 ...