Directive Controller And Link Timing In AngularJS
I've talked about the timing of directives in AngularJS a few times before. But, it's a rather complicated topic, so I don't mind digging a bit deeper. This time, I'm looking at the timing of directive controllers vs. directive link functions. As the DOM (Document Object Model) is compiled by AngularJS, the directive controllers and link functions execute at different parts of the compile lifecycle.
When AngularJS compiles the DOM, it walks the DOM tree in a depth-first, top-down manner. As it walks down the DOM, it instantiates the directive controllers. Then, when it gets to the bottom of a local DOM tree branch, it starts linking the directives in a bottom-up manner as it walks back up the branch. This doesn't mean that all directive controllers are run before all directive linking; it simply means that in a local DOM branch, the directive controllers are instantiated before they are linked.
To see this in action, I've put together a very simple DOM tree in which each element has a unique (but almost identical) directive. As each directive controller and link function is executed, it will log to the console. This way, we can see the timing of the various methods in relation to the DOM tree structure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | <!doctype html> <html ng-app= "Demo" > <head> <meta charset= "utf-8" /> <title> Directive Controller And Link Timing In AngularJS </title> </head> <body> <h1> Directive Controller And Link Timing In AngularJS </h1> <div bn-outer> <p bn-mid> <span bn-inner> Woot! </span> </p> <p bn-second-mid> Woot, indeed! </p> </div> <!-- Load scripts. --> <script type= "text/javascript" src= "../../vendor/jquery/jquery-2.0.3.min.js" ></script> <script type= "text/javascript" src= "../../vendor/angularjs/angular-1.2.4.min.js" ></script> <script type= "text/javascript" > // Create an application module for our demo. var app = angular.module( "Demo" , [] ); // -------------------------------------------------- // // -------------------------------------------------- // // I demonstrate the timing of directive execution. app.directive( "bnOuter" , function () { function Controller( $scope ) { console.log( "Outer - Controller" ); } function link( $scope, element, attributes, controller ) { console.log( "Outer - Link" ); } // Return directive configuration. return ({ controller: Controller, link: link }); } ); // -------------------------------------------------- // // -------------------------------------------------- // // I demonstrate the timing of directive execution. app.directive( "bnMid" , function () { function Controller( $scope ) { console.log( "Mid - Controller" ); } function link( $scope, element, attributes, controller ) { console.log( "Mid - Link" ); } // Return directive configuration. return ({ controller: Controller, link: link }); } ); // -------------------------------------------------- // // -------------------------------------------------- // // I demonstrate the timing of directive execution. app.directive( "bnSecondMid" , function () { function Controller( $scope ) { console.log( "Second Mid - Controller" ); } function link( $scope, element, attributes, controller ) { console.log( "Second Mid - Link" ); } // Return directive configuration. return ({ controller: Controller, link: link }); } ); // -------------------------------------------------- // // -------------------------------------------------- // // I demonstrate the timing of directive execution. app.directive( "bnInner" , function () { function Controller( $scope ) { console.log( "Inner - Controller" ); } function link( $scope, element, attributes, controller ) { console.log( "Inner - Link" ); } // Return directive configuration. return ({ controller: Controller, link: link }); } ); </script> </body> </html> |
Before we look at the console output, take note that there are two "mid" branches. This means that AngularJS has two branches to explore before it can fully walk back up to the top DOM node. That said, when we do run the above code, we get the following console log output:
Outer - Controller
Mid - Controller
Inner - Controller
Inner - Link
Mid - Link
Second Mid - Controller
Second Mid - Link
Outer - Link
As you can see, as AngularJS walks the DOM tree, it instantiates the directive controllers on the way down; then, it links the directives on the way back up.
This is an important difference. While you can only access the DOM tree in the bottom-up linking phase, the directive controller can provide a hook into the top-down lifecycle. This can be critical if you have to handle DOM events based on when elements of the DOM tree came into existence. The linking phase can never give you that because it's executed in reverse.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2017-07-05 go语言中log包的使用
2017-07-05 go语言使用官方的 log package 来记录日志