angular.js指令中的controller、compile与link函数的不同之处


Posted in Javascript onMay 10, 2017

前言

算了算用angualrjs去做开发也有两个月了,但做为一个菜鸟,难免会被大神吊打(这里有一个悲伤的故事...)。某天一位前端大神问我:你知道angular指令中的controller,compile,link函数有什么不同?然后我就一脸懵逼了....于是决定深入的去探究下。

今天我们来一起了解一下它们有什么不同的地方:

先看一段示例代码

var ag = angular.module("myApp",[]);
  ag.controller("myCtrl",["$rootScope",function($rootScope){

  }]);
  ag.directive("order",function(){
   return{
    restrict:"AE",
    controller:function($scope, $element, $attrs, $transclude) {
     console.log("controller");
    },
    compile:function(tElement, tAttrs, transclude){
     console.log("compile");
     return{
      pre:function(scope, iElement, iAttrs, controller){
       console.log("pre")
      },
      post:function(scope, iElement, iAttrs, controller){
       console.log("post")
      }
     }
    },
    link:function(scope, iElement, iAttrs, controller){
     console.log("link")
    }
   }
  });

我们可以看到什么order指令中写了controller, complie, link函数;我们可以思考一下上面会输出一下什么来.

angular.js指令中的controller、compile与link函数的不同之处

从上面的输出结果我们可以得出两个结论:

  • 他们的执行顺序不同,最先执行的是complie函数 ; 然后是controller函数,然后是pre函数,最后是post函数.
  • link函数没有执行.

首先我们来解释第一个问题;看下图

angular.js指令中的controller、compile与link函数的不同之处

从图中我们可以看到整个 AngularJs 的生命周期分为两个阶段:

第一个阶段是编译阶段:

在编译阶段,AngularJS会遍历整个HTML文档并根据JavaScript中的指令定义来处理页面上声明的指令。每一个指令的模板中都可能含有另外一个指令,另外一个指令也可能会有自己的模板。当AngularJS调用HTML文档根部的指令时,会遍历其中所有的模板,模板中也可能包含带有模板的指令.一旦对指令和其中的子模板进行遍历或编译,编译后的模板会返回一个叫做模板函数的函数。我们有机会在指令的模板函数被返回前,对编译后的DOM树进行修改。

ag.directive("order",function(){
 return{
  restrict:"AE",
  compile:function(tELe ,tAttrs,transcludeFn){
    //进行编译后的dom操作
    return{
      pre:function(scope, iElement, iAttrs, controller){
       // 在子元素被链接之前执行
       // 在这里进行Dom转换不安全
      },
      post:function(scope, iElement, iAttrs, controller){
       // 在子元素被链接之后执行
      }
     }
  }
 }
})

第二个阶段是链接阶段:

链接函数来将模板与作用域链接起来;负责设置事件监听器,监视数据变化和实时的操作DOM.链接函数是可选的。如果定义了编译函数,它会返回链接函数,因此当两个函数都定义了时,编译函数会重载链接函数.(解释上面的结论2)

var ag = angular.module("myApp",[]);
  ag.controller("myCtrl",["$rootScope",function($rootScope){

  }]);
  ag.directive("order",function(){
   return{
    restrict:"AE",
    controller:function($scope, $element, $attrs, $transclude) {
     console.log("controller");
    },
    link:function(scope, iElement, iAttrs, controller){
     console.log("link")
    }
   }
  });

上面指令执行时;会输出:

angular.js指令中的controller、compile与link函数的不同之处

我们可以看到controller函数先执行,然后是link函数.但是链接阶段会执行controller,link函数;那么他们有什么不同;我们在什么情况该用哪个?

答案是:

指令的控制器和link函数可以进行互换。控制器主要是用来提供可在指令间复用的行为,但链接函数只能在当前内部指令中定义行为,且无法在指令间复用.link函数可以将指令互相隔离开来,而controller则定义可复用的行为。
实际使用的一些建议:

如果我们希望将当前指令的API暴露给其他指令使用,可以使用controller参数,否则可以使用link来构造当前指令元素的功能性。如果我们使用了scope.$watch()或者想要与DOM元素做实时的交互,使用链接会是更好的选择。

到这里:我们应该有一点了解这三者有什么差异了吧?其实这个问题考的就是我们对AngularJs生命周期的了解.

最后我们用一个实际例子来看一下AngularJs的生命周期:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
 <div parent>
  <div child></div>
 </div>
<script src="../plugins/angularjs/angular.src.js"></script>
<script>
 var ag = angular.module("myApp",[]);
  ag.controller("myCtrl",["$rootScope",function($rootScope){

  }]);
  ag.directive("parent",function(){
   return{
    restrict:"AE",
    controller:function($scope, $element, $attrs, $transclude) {
     console.log("parent controller");
    },
    compile:function(tElement, tAttrs, transclude){
     console.log("parent compile");
     return{
      pre:function(scope, iElement, iAttrs, controller){
       console.log("parent pre")
      },
      post:function(scope, iElement, iAttrs, controller){
       console.log("parent post")
      }
     }
    }
   }
  });
 ag.directive("child",function(){
  return{
   restrict:"AE",
   controller:function($scope, $element, $attrs, $transclude) {
    console.log("child controller");
   },
   compile:function(tElement, tAttrs, transclude){
    console.log("child compile");
    return{
     pre:function(scope, iElement, iAttrs, controller){
      console.log("child pre")
     },
     post:function(scope, iElement, iAttrs, controller){
      console.log("child post")
     }
    }
   }
  }
 });
</script>
</body>
</html>

结果如图:

angular.js指令中的controller、compile与link函数的不同之处

可以参照上面的angularjs生命周期图来理解.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Jquery在IE7下无法使用 $.ajax解决方法
Nov 11 Javascript
动态加载图片路径 保持JavaScript控件的相对独立性
Sep 03 Javascript
JavaScript中的console.trace()函数介绍
Dec 29 Javascript
js简单实现标签云效果实例
Aug 06 Javascript
Node.js读写文件之批量替换图片的实现方法
Sep 07 Javascript
jQuery ajax MD5实现用户注册即时验证功能
Oct 11 Javascript
jQuery ajax 当async为false时解决同步操作失败的问题
Nov 18 Javascript
Vue2 添加数据可视化支持的方法步骤
Jan 02 Javascript
微信小程序云开发修改云数据库中的数据方法
May 18 Javascript
Vue移动端用淘宝弹性布局lib-flexible插件做适配的方法
May 26 Javascript
javascript解析json格式的数据方法详解
Aug 07 Javascript
JS新手入门数组处理的实用方法汇总
Apr 07 Javascript
详解vue-router 2.0 常用基础知识点之导航钩子
May 10 #Javascript
详解vue-router 2.0 常用基础知识点之router.push()
May 10 #Javascript
JavaScript通过filereader接口读取文件
May 10 #Javascript
关于vue-router路径计算问题
May 10 #Javascript
JavaScript使用readAsDataUrl方法预览图片
May 10 #Javascript
Bootstrap table使用方法总结
May 10 #Javascript
将angular-ui的分页组件封装成指令的方法详解
May 10 #Javascript
You might like
让你同时上传 1000 个文件 (一)
2006/10/09 PHP
PHP7新功能总结
2019/04/14 PHP
用正则xmlHttp实现的偷(转)
2007/01/22 Javascript
用js自动判断浏览器分辨率的代码
2007/01/28 Javascript
javascript instanceof 与typeof使用说明
2010/01/11 Javascript
javascript使用isNaN()函数判断变量是否为数字
2013/09/21 Javascript
Express的路由详解
2015/12/10 Javascript
JavaScript小技巧整理篇(非常全)
2016/01/26 Javascript
jQuery图片左右滚动代码 有左右按钮实例
2016/06/20 Javascript
js实现瀑布流效果(自动生成新的内容)
2017/03/16 Javascript
微信小程序与php 实现微信支付的简单实例
2017/06/23 Javascript
Vue动态组件实例解析
2017/08/20 Javascript
vue项目中,main.js,App.vue,index.html的调用方法
2018/09/20 Javascript
vue axios请求频繁时取消上一次请求的方法
2018/11/10 Javascript
JS实现带阴历的日历功能详解
2019/01/24 Javascript
简单易扩展可控性强的Jquery转盘抽奖程序
2019/03/16 jQuery
JavaScript(js)处理的HTML事件、键盘事件、鼠标事件简单示例
2019/11/19 Javascript
ES6学习笔记之字符串、数组、对象、函数新增知识点实例分析
2020/01/22 Javascript
[38:41]2014 DOTA2国际邀请赛中国区预选赛 LGD VS CNB
2014/05/22 DOTA
Python面向对象程序设计OOP入门教程【类,实例,继承,重载等】
2019/01/05 Python
Django框架组成结构、基本概念与文件功能分析
2019/07/30 Python
new_zeros() pytorch版本的转换方式
2020/02/18 Python
纯CSS3代码实现switch滑动开关按钮效果
2016/08/30 HTML / CSS
CSS3 translate导致字体模糊的实例代码
2019/08/30 HTML / CSS
世界领先的高品质定制产品平台:Zazzle
2017/07/23 全球购物
台湾生鲜宅配:大口市集
2017/10/14 全球购物
少先队学雷锋活动月总结
2014/03/09 职场文书
消防安全宣传标语
2014/06/07 职场文书
环境保护与污染治理求职信
2014/07/16 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
校运动会广播稿300字
2014/10/07 职场文书
班主任经验交流心得体会
2015/11/02 职场文书
幼儿园小班开学寄语(2016秋季)
2015/12/03 职场文书
如何判断微信付款码和支付宝付款码
2021/04/01 PHP
Python - 10行代码集2000张美女图
2021/05/23 Python
排查MySQL生产环境索引没有效果
2022/04/11 MySQL