发表于: 2017-07-09 23:26:28

1 976


如何理解angular自定义指令directivecompilelink属性?
小课堂【武汉第166期】
分享人:肖浩宇



1.
背景介绍


   
指令是angularjs最重要的特性之一,通过自定义指令,我们可以将htmljs封装成一个独立的模块,使HTML标签的范围扩展到无穷大。在directivecompilelink是其最重要的两个属性。



2.知识剖析

自定义指令的基本结构:

dirAppModole.directive('directive-name',function(){
   var obj = {
       restrict:'string',
priority:number,
template:'string',
templateUrl:'string',
replace:bool,
transclude:bool or 'element',
scope:bool or string,
controller:function(){},
require:'string',
link: function(scope,iEle,iAttrs,ctrl,linker){},
compile: function(tEle,tAttrs,linker){
           return {
               pre: function(scope,iEle,iAttrs,ctrl){},
post: function(scope,iEle,iAttrs,ctrl){}
           }
       }
   };
   return obj
});


link函数:


link:function(scope,iEle,iAttrs,ctrl,linker){
   ....
}



如上,link5个参数::scope,iEle,iAttrs,ctrl,linker

1.scope:
指令所在的作用域,这个scope和指令定义的scope属性是一致的.
2.iEle:
指令元素本身,可进行jq操作
3.iAttrs:
指令元素的属性的集合
4.ctrl:
需要和require属性一起使用,用于调用其他指令的方法,指令之间的互相通信,
5.linker:
transclude()函数,自定义指令的transclude属性有关。


compile函数:
compile
函数有三个参数:tEle,tAttrs,linker:

1.tEle:
指令元素本身,可进行jq操作.
2.tAttrs:
指令元素的属性的集合
3.linker
函数:transclude()函数.


compile
的返回值:compile函数返回值有两种可能:

返回pre-link函数和post-link函数
只返回post-link函数


3.常见问题

compilelink有什么不同?


4.解决方案

要解决这个问题需从指令的解析流程讲起:
    1.ng
框架会在页面载入完毕的时候,根据 ng-app 划定的作用域来调用 $compile 服务进行编译,清点作用域内的 DOM 元素,然后根据这些指令的优先级 (priority)
排列一下,根据指令中的配置参数 (templatetransclude ) 转换 DOM,让指令初具人形
     2.
然后就开始按顺序执行各指令内的 compile 函数,注意此处的 compile 不是 $compilecompile 函数中可以访问到 DOM 节点并进行操作,其主要职责就是进行
DOM
转换,每个compile 函数执行完后都会返回compile内的link函数,这些 link 函数会被$compile汇合一下组合成一个合体后的 link 函数。

    3.
接下来进入 link 阶段,合体后的 link 函数被执行。所谓的链接,就是把 view scope 链接起来。这就是我们熟悉的数据绑定,通过在 DOM 上注册监听器来动态修改
scope
中的数据,或者是使用 $watchs 监听 scope 中的变量来修改 DOM,从而建立双向绑定。由此也可以断定,合体的link可以访问到 scope DOM 节点。
    4
若没有配置 compile 函数? $compile 就把这里的 link 函数拿来执行。配置的 link 函数也可以访问到 scope 以及 DOM 节点。compile
函数通常是不会被配置的,因为我们定义一个指令的时候,大部分情况不会通过编程的方式进行 DOM 操作,而更多的是进行监听器的注册、数据的绑定。


   
由上可知,compilelink不能共存,两者的参数中都有ele,都是获取指令元素本身,不同的是,compile 拿到的是编译前的,是从 template 里拿过来的,而 link
拿到的是编译后的,已经与作用域建立了关联,这也正是 link 中可以进行数据绑定的原因。


5.编码实战

https://ptteng.github.io/PPT/demo/JS-11-The%20compile%20and%20link%20of%20directive/demo1.htmlDEMO1


6.扩展思考

几个指令嵌套时compilepre-linkpost-link的执行顺序?
https://ptteng.github.io/PPT/demo/JS-11-The%20compile%20and%20link%20of%20directive/demo2.html

DEMO2


7.参考文献


参考一:流浪猫の窝-angular学习笔记(三十)-指令(7)-compile和link

http://www.cnblogs.com/liulangmao/p/3980144.html


参考二:吕大豹-走进AngularJs(三)自定义指令

http://www.cnblogs.com/lvdabao/p/3391634.html


8.更多讨论

1.为什么为什么编译的过程要分成compilelink?

简单的说就是为了解决性能问题,特别是那种model变化会影响dom结构变化的,而变化的结构还会有新的scope绑定及事件绑定,比如ng-repeat

 

2. compilelink的使用时机?

Compile:想在dom渲染前对它进行变形,并且不需要scope参数想在所有相同directive里共享某些方法,这时应该定义在compile里,性能会比较好返回值就是linkfunction,这时就是共同使用的时候

Link:对特定的元素注册事件需要用到scope参数来实现dom元素的一些行为



6个问题:

1.怎么查找资料

a.善用google搜索,比百度靠谱。

b.博客园,segmentfault,csdn的资料比较靠谱,知乎上也有很多程序员。

c.搜索的一点小技巧:关键词加引号代表精确搜索,关键词前加filetype:pdf 可搜索特定的文件类型。


2.怎么定位问题

a.在webstorm中有快捷键F2

b.看控制台提示

c.控制台source界面打断点查看

d.分段注释代码查看运行情况


3.怎么解决问题

a.根据代码错误提示查找关键词

b.在StackOverflow上搜索

c.问师兄


4.怎么重构代码

a.webstorm快捷键ctrl+alt+l

b.控制台sources面板中点击左下角


5.怎么选择框架

a.随大流,使用行业经常用的,比较出名的。

b.根据自己的需求选择


6.怎么测试

还没做过,不太清楚。





返回列表 返回列表
评论

    分享到