指令的执行过程分析。

我们知道指令的执行分两个阶段,一个是compile,一个是link。

我们可以在指令中自定义compile和link。

首先,我们来讲解如何自定义link函数

举个例子:

<!doctype html>
<html ng-app="myModule">
<head>
</head>
<body>
    <hello></hello>
</body>
<script src="angular.js"></script>
<script src="helloAngular.js"></script>
</html>

helloAngular.js代码

var myModule = angular.module("myModule", []);
myModule.directive("hello", function(){
return {
  restrict: "E",
     template: "<div>Hello,Angular</div>",
     replace: true,
link: function(scope, el, attrs, controller){
       el.on("click", function(){
          alert("鼠标点击");
       });
     }
}
});

link方法一般用来对元素进行处理。这里是对元素进行事件的绑定。当用户元素div进行点击时,会弹出鼠标点击的框。

然后,我们来讲解如何自定义compile函数

<!doctype html>
<html ng-app="myModule">
<head>
</head>
<body>
    <div hellos="3">
      <p>hello,Angular!</p>
    </div>
</body>
<script src="angular.js"></script>
<script src="helloAngular.js"></script>
</html>

helloAngular.js代码

var myModule = angular.module("myModule", []);
myModule.directive("hellos", function(){
return {
  restrict: "A",
compile: function(el, attrs, transclude){
       alert("指令编译");
        var tpl = el.children().clone(); //p标签以及内容
        for(var i =0;i<attrs.hellos -1;i++){
          el.append(tpl.clone());
        }
        return function(scope, el, attrs, controller){ //compile必须要return这样的一个函数,这个函数其实就是link函数,在链接阶段,就会执行此link函数。
          alert("指令链接");
        }
     }
}
});

当页面加载进来后,就会弹出指令编译,然后再弹出指令链接的框。

如果,我们在上面的helloAngular.js中,不仅自定义了compile方法,而且也自定义了link方法。比如:

var myModule = angular.module("myModule", []);
myModule.directive("hellos", function(){ //定义一个hellos指令
return {
  restrict: "A",
compile: function(el, attrs, transclude){
       alert("指令编译");
        var tpl = el.children().clone(); //p标签以及内容
        for(var i =0;i<attrs.hellos -1;i++){
          el.append(tpl.clone());
        }
        return function(scope, el, attrs, controller){ //compile必须要return这样的一个函数,这个函数其实就是link函数,在链接阶段,就会执行此link函数。
          alert("指令链接");
        }      }
     link : function(scope, el, attrs, controller){
        alert("自定义的link");
     }
}
});

当页面加载进来时,自定义的link不会弹出来。意思就是说,当存在compile时,不会执行你自定义的link函数,因为angular会把compile返回的函数当做link函数来执行。当不存在compile时,就会执行你自定义的link函数。

compile函数很少被用到,写起来比较麻烦。

compile函数的作用是对指令的模板进行转换,比如,上面的例子中,compile函数就把指令的模板进行了叠加,改变了页面上的DOM结构。

link函数的作用是在模型和视图之间建立关联,同时在元素上绑定事件监听。

scope在链接阶段才会被绑定到元素上,因此在compile中操作scope会报错。

对于同一个指令的多个实例,compile只会执行一次,而link对于指令的每个实例都会执行一次。比如:ng-repeat指令,如果元素的ng-repeat=3,那么ng-repeat指令的compile只会执行一次,而link会执行三次。

对于指令,我们一般只需要自定义link函数就行了。

接下来,我们来讲解使用compile服务,在页面上查找指令并编译指令的过程:

从ng-app开始,递归子层的DOM结构,收集指令,然后在ng-app指令的位置创建$rootScope作用域。比如:上面的代码中,我们注册了一个hellos指令,angular在启动时,就会遍历DOM去查找这个指令。

如果有需要,会为指令生成childScope。

调用每个指令自己的compile函数,生成自己的compositeLinkFn函数。

编译的结果是返回一个publicLinkFn函数。

编译完成之后立即调用生成的publicLinkFn函数。

angular对tree型的数据结构进行双向绑定时,不太理想,性能消耗太大。

加油!

angular核心原理解析3:指令的执行过程的更多相关文章

  1. angular核心原理解析1:angular自启动过程

    angularJS的源代码整体上来说是一个自执行函数,在angularJS加载完成后,就会自动执行了. angular源代码中: angular = window.angular || (window ...

  2. angular核心原理解析2:注入器的创建和使用

    上一课没有讲到创建注入器的方法createInjector. 此方法,会创建两种不同的注入器:第一种叫做providerInjector,第二种叫做instanceInjector.providerI ...

  3. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  4. Java并发包JUC核心原理解析

    CS-LogN思维导图:记录CS基础 面试题 开源地址:https://github.com/FISHers6/CS-LogN JUC 分类 线程管理 线程池相关类 Executor.Executor ...

  5. ibatis 核心原理解析!

    关注下方公众号,可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料. 最近查找一个生产问题的原因,需要深入研究 ibatis 框架的源码.虽然最后证明问题的原因与 ibat ...

  6. ibatis 核心原理解析

    最近查找一个生产问题的原因,需要深入研究 ibatis 框架的源码.虽然最后证明问题的原因与 ibatis 无关,但是这个过程加深了对 ibatis 框架原理的理解. 这篇文章主要就来讲讲 ibati ...

  7. Promise核心原理解析

    作者: HerryLo 本文永久有效链接: https://github.com/AttemptWeb...... Promises对象被用于表示一个异步操作的最终完成 (或失败), 及其结果值.主要 ...

  8. 「进阶篇」Vue Router 核心原理解析

    前言 此篇为进阶篇,希望读者有 Vue.js,Vue Router 的使用经验,并对 Vue.js 核心原理有简单了解: 不会大篇幅手撕源码,会贴最核心的源码,对应的官方仓库源码地址会放到超上,可以配 ...

  9. NameServer 核心原理解析

    在之前的文章中,已经把 Broker.Producer 和 Conusmer 的部分源码和核心的机制介绍的差不多了,但是其实 RocketMQ 中还有一个比较关键但是我们平时很容易忽略的组件--Nam ...

随机推荐

  1. the difference between fopen&open

    [the difference between fopen&open] fopen是C标准API,open是linux系统调用,层次上fopen基于open,在其之上.fopen有缓存,ope ...

  2. linux之badblocks命令

    简介 该命令用来检测硬盘坏道.硬盘坏道问题,如忽视,会随着使用而扩大面积,严重损坏硬盘.一般采用检测坏道,进而屏蔽重分区的方式复用硬盘. 语法 badblock(选项)(参数) -b<区块大小& ...

  3. ios 解决Wkwebview闪烁问题

    // 网页闪烁问题    if ([self.webView.realWebView isKindOfClass:[WKWebView class]]) {         ((WKWebView * ...

  4. 用Diff和Patch工具维护源码

    在Unix系统下,维护源码版本可以使用很多方法,其中最常用的当然是大名鼎鼎的CVS,但实际上,简单的版本维护工作并没有必要使用复杂的CVS等专门的版本维护工具,Unix标配中的diff和patch工具 ...

  5. Linux&&Mac 自动增加CSDN访问量

    我心里面有两个小人. 一个叫愧疚,对CSDN这么一个分享知识的平台的愧疚,因为我正在做一件对不起CSDN的事情. 一个叫虚荣,对CSDN访问量的渴望过渡使得我踏出了这一步. 这一步,踏入了深渊.. 最 ...

  6. [SoapUI]获取Project,Test Suite,Test Case各个级别参数的值

    String testResultPath = testRunner.testCase.testSuite.project.getPropertyValue( "testResultPath ...

  7. 为什么都说UX / UI设计师是最佳工作?

    以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 你将成为永远热爱自己工作的人,做着自己喜欢的工作还能得到相应的成果和报酬,就好似在度带薪年假一般,何 ...

  8. Caffe 议事(三):从零开始搭建 ResNet 之 网络的搭建(中)

    上面2个函数定义好了,那么剩下的编写网络就比较容易了,我们在ResNet结构介绍中有一个表,再贴出来: Layer_name Output_size 20-layer ResNet Conv1 32 ...

  9. mvc api odata查询选项之 $inlinecount $format 选项(转)

    出处:http://www.it165.net/pro/html/201505/40236.html 网上百度“odata 语法”会出来很多结果,其中有一项是比较一致的,那就是odata支持一下几种语 ...

  10. win10自带虚拟机安装CentOS7系统(转)

    出处:http://blog.csdn.net/bimabushihaodongxi/article/details/53677490 话说工欲善其事,必先利其器,在我准备学习Linux之前先要完成l ...