AngularJS 指令生命周期 complie link
AnguarJS指令从解析到生效一共会经历Inject、Compile、Controller加载、Pre-link、Post-link这几个主要阶段。
一、AngularJS指令执行过程
1、加载Angularjs,找到ng-app,确定应用的边界。.将html转换为DOM
2、遍历DOM,找到所有指令,并编译,执行directive上的complie方法。想在dom渲染前对它进行变形(修改DOM),并且不需要scope参数
想在所有相同directive里共享某些方法,定义在compile里,性能会比较好。编译模板,把表达式{{}}解析成一种特殊的指令:addTextInterpolateDirective。
3、对每一条指令运行link函数;link函数一般用来操作DOM,绑定事件监听器,监听数据变化,执行directive上的link方法,该方法主要进行scope绑定及事件绑定。对表达式用$watch的API来注册watchers函数
二、通过例子解析生命周期
- angular.module('com.ngnice.app').directiveLift('directiveLift',function($log){
//1、Injecting- $log.info('Injecting function directiveLife');
- return {
- restrict:'EA',
- transclude:true,
- replace:true,
- template:'<div><h2>count:{{count}}</h2><p ng-transclude></p></div>',
- scope:{
- count:'='
- },
- compile:function(elm,iAttrs){
//2、- $log.info('compile','count value from attribute:'+iAttrs.count);
- return {
- pre:function(scope,elm, iAttrs){
- $log.info('pre-link','count value from attribute:'+iAttrs.count,'count value from scope:'+scope.count);
- },
- post:function(scope,elm, iAttrs){
- $log.info('pre-link','count value from attribute:'+iAttrs.count,'count value from scope:'+scope.count);
- }
- };
- },
- controller:function($scope){
- $log.info('controller', 'count value from controller:' + $scope.count);
- }
- };
- });
- angular.modele('com.ngnice.app').controller('DemoController',function(){
- var vm = this,
- return vm;
- });
执行结果:
1、Injecting
Injecting function directiveLife位置是所有directiveLife指令共享的作用域,可以在这里设置directive默认配置,但是,这类信息有更好的方式进行配置,建议不要这么做,可 以把这类配置信息抽取成Constant,其也是一种全局共享的服务,再注入到指令中,或者在config阶段对默认配置进行定制。其首次解析指令时候执行一次,最多执行一次,如 果不用指令,一次也不执行。
2、Complie
接下来执行compile函数,每次实例化指令的时候都调用一次,其有两个参数,原始的Dom元素节点,和它所包含的Attribute的信息,这里传入的DOM节点是初始的DOM节点 没有Link过,虽然在这里可以检查DOM信息和将被执行的表达式,但是不能访问$scope,也不能求出表达式的值,然而,这里是修改节点、插入子模版或兄弟节点的好时机, 稍后,它们就会被Angular自动编译,而不需要我们手动编译它。compile函数最有一句返回后边要用的link函数,包括pre-link和post-link函数。
3、Controller加载
在进入Link阶段之前,AngularJS会根据我们在指令中定义Scope,创建独立或非独立的作用域scope,然后,调用指令中的Controller初始化Scope,这里不涉及任何DOM节 点信息,但是我们可以用AngularJS的$injector注入$scope,这里也是唯一能复用的逻辑,不涉及DOM信息,只包含业务逻辑代码。
3、Link
Controller初始化指令$scope后,将进入真正的解析过程,分两个阶段:pre-link和post-link,对于指令的每个实例来说也执行一次,对于ngRepeat来说每个item执行一次。因 为在Controller加载阶段已经初始化好$scope对象,所以这里的$scope已经可用,注意的是这里的scope对象是传入的参数,和Controller不同,不是被注入的。此时,每个表达 式都有确定的值,AngularJS开始将模版渲染到DOM。如果想在这里添加模版,已经迟了,AngularJS不会帮忙自动解析,必须手动调用$compile编译、链接它,并插入到指定 DOM中。
(1)、pre-link
在plink阶段,pre-link时,子DOM的结构还没有稳定,不适合去添加设计子DOM的行为和监听事件,但是是初始化下级指令需要数据的合适时机。如果下级指令需要得到一 些初始化设置数据,那么应该写在pre-link函数中,我们的最佳实践是在Controller中初始化这类数据,但是如果需要DOM信息才能初始化的情况,只能写在pre-link函数中。
(2)、post-link
在指令的开发中,用的最多还是post-link,而不是pre-link,此时,它执行时候,内嵌的指令已经已经被链接过,可以安全的为当前节点或子节点添加某些行为或事件监听函 数,使当前的DOM具有我们期望的能力,自动聚焦或双向绑定。
三、注意点
1、link函数
(1)、link函数代表的是complie返回的postLink函数;
(2)、preLink表示在编译阶段之后,在子元素被链接之前执行;
(3)、postLink会在所有子元素被链接之后执行;
用link函数创建可以操作DOM的指令。链接函数是可选的。如果定义了编译函数,它会返回链接函数,因此当两个函数都定义了时,编译函数会重载链接函数。当定义了编译函数来取代链接函数时,链接函数是我们能提供给返回对象的第二个方法,也就是postLink函数。本质上讲,这个事实正说明了链接函数的作用。它会在模板编译并同作用域进行链接后被调用,因此它负责设置事件监听器,监视数据变化和实时的操作DOM。
注意下:Controller是注入$scope,llink函数是Scope参数对象。
2、控制器和link
控制器主要是用来提供可在指令间复用的行为,但链接函数只能在当前内部指令中定义行为,且无法在指令间复用.link函数可以将指令互相隔离开来,而controller则定义可复用的行为。
3、编译和链接阶段总结
编译阶段:
链接阶段:
四、例子(compile函数)
- var i=0;
- angular.module('myApp',[])
- //定义第一个指令:customTags
- .directive('customTags',function(){
- return {
- restrict:'ECAM',
- template:'<div>{{ user.name }}</div>',
- replace:true,
- //定义了compile就不需定义link,当compile返回一个方法这个方法就是link
- //tElement 正在执行该指令的当前dom元素的jquery对象
- //tAttrs 正在执行该指令的当前dom元素的属性
- compile:function(tElement,tAttrs,transclude){
- //第一个指令的编译阶段...
- console.log('customTags compile 编译阶段...');
- //若要改变dom元素,应在compile中做,此处在当前dom元素中添加一个<span>
- tElement.append(angular.element('<span> {{user.count}}</span>'));
- return {
- //pre:编译阶段之后执行
- pre:function preLink(scope,iElement,iAttrs,controller){
- console.log('customTags preLink..');
- },
- //post:所有子元素指令的post都执行后执行,此处设置了dom元素的点击事件
- post:function postLink(scope,iElement,iAttrs,controller){
- iElement.on('click',function(){
- scope.$apply(function(){
- scope.user.name=' click after';
- scope.user.count= ++i;
- });
- });
- console.log('customTags post end.');
- console.log('');
- }
- };
- //compile也可直接返回一个方法,这就是 postLink,也就是上面的post
- /*return function (){
- console.log('compile return this function')
- }*/
- },
- //进行scope绑定及事件绑定
- link:function(scope,iElement,iAttrs,bookListController){
- //link不会再执行了,因为这里定义的就是postLink
- }
- }
- })
AngularJS 指令生命周期 complie link的更多相关文章
- VUE自定义指令生命周期,VUE生命周期
一.自定义指令的生命周期 自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind bind:只调用一次,指令第一次绑 ...
- vue_实例_组件的生命周期
重绘重排 中重复出现的是 mounted(){...} beforeUpdate(){...} uptated(){...} 其他钩子函数只会出现一次 <!DOCTYPE html> & ...
- Angular4学习笔记(九)- 生命周期钩子简介
简介 Angular 指令的生命周期,它是用来记录指令从创建.应用及销毁的过程.Angular 提供了一系列与指令生命周期相关的钩子,便于我们监控指令生命周期的变化,并执行相关的操作.Angular ...
- angular、angular2、vue的生命周期
angular生命周期是什么 1.Angular每个组件都存在一个生命周期,从创建,变更到销毁.Angular提供组件生命周期钩子,把这些关键时刻暴露出来,赋予在这些关键结点和组件进行交互的能力,掌握 ...
- angular2的生命周期钩子的使用情况
angular 2 Directive Lifecycleangular2 中组建继承于指令,并扩展了与ui视图相关的属性.angular2 指令的生命周期是用来记录指令从创建,应用及销毁的过程.an ...
- angularjs link compile与controller的区别详解,了解angular生命周期
壹 ❀ 引 我在 angularjs 一篇文章看懂自定义指令directive 一文中简单提及了自定义指令中的link链接函数与compile编译函数,并说到两者具有互斥特性,即同时存在link与c ...
- 理解AngularJS生命周期:利用ng-repeat动态解析自定义directive
ng-repeat是AngularJS中一个非常重要和有意思的directive,常见的用法之一是将某种自定义directive和ng-repeat一起使用,循环地来渲染开发者所需要的组件.比如现在有 ...
- 【转】angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- Vue01 Vue介绍、Vue使用、Vue实例的创建、数据绑定、Vue实例的生命周期、差值与表达式、指令与事件、语法糖
1 Vue介绍 1.1 官方介绍 vue是一个简单小巧的渐进式的技术栈,它提供了Web开发中常用的高级功能:视图和数据的解耦.组件的服用.路由.状态管理.虚拟DOM 说明:简单小巧 -> 压缩后 ...
随机推荐
- linux-ubuntu 下R无法安装rjava模块的原因及解决方案
错误信息: 没有 /usr/lib/jvm/default-java/jre/bin/java 原因: R找不到java作为依赖 解决方案: (1) 如果你没有安装java,请先安装java. (2) ...
- tomcat 、eclipse插件安装、一个机器安装多个tomcat、tomcat闪退的问题解决
一.正常情况下 (1)新建三个系统变量:tomcat的安装路径 TOMCAT_HOME=E:\tomcat-6.0.39 CATALINA_HOME=E:\tomcat-6.0.39 CATALINA ...
- 2017/2/10:Manven简介与项目管理(入门)
1.Maven工程的创建 2.使用Manven manven配置文件主要集中在 http://m.blog.csdn.net/article/details?id=50316383
- [Oracle]ORA-14400:插入的分区关键字未映射到任何分区
今天在使用测试库的时候发生ORA-14400:inserted partition key does not map to any partition 解决过程: 经过百度,发现出现ORA-14400 ...
- ubuntu samba共享后windows读写文件都是以nogroup问题
添加smb账号 sudo smbpasswd -a xxx 如果报错:Failed to add entry for user xxx 则是因为这个账号不存在 添加成功以后,过一会就可以重新登陆了(u ...
- 2018.12.22 bzoj3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)
传送门 题意简述:给出一棵trietrietrie树,每个点表示一个字符,求树上所有路径组成的不同字串数.(叶子数≤20\le 20≤20) 由于有一个神奇的条件,考虑以每一个叶子为树根统计每个点到树 ...
- C#装箱,拆箱和强制转换(转)
出处:https://www.cnblogs.com/fengjiulin110120/p/6605739.html 关系: 强制转换就包含有装箱拆箱操作,装箱就是把值类型转换成引用类型,反之就是拆箱 ...
- TCP/IP协议(6):传输层之UDP
一. UDP用户数据报协议,它是一个无连接的,面向数据报的协议,它不提供可靠性但传输速度比TCP要快. UDP数据报中的“UDP长度”为两个字节,所以我们要发送的UDP数据最多支持65507大约68K ...
- Spring Boot 入门实践
一.Eclipse配置Spring Boot环境 1.查看eclipse版本信息: 2.登录:http://spring.io/tools/sts/all 看eclipse对应的插件版本对应的ecli ...
- git 如何更改某个提交内容/如何把当前改动追加到某次commit上? git rebase
原文地址 http://www.jianshu.com/p/8d666830e826 [自己总结] 0, git diff git diff a b 是以a为基准,把b和a的区别展示出来 ...