角度指令 - 编译Vs链接 - 编译不渲染一次

时间:2016-04-28 10:00:48

标签: javascript angularjs angularjs-directive

我有以下代码。我希望编译只运行一次,并链接运行5次。

<html>
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js" ></script> 
    <style>.red{color:red;}.blue{background:blue;}</style>
</head>
<body ng-app="myApp" ng-controller="myCtrl"> 
<div hello dear> 1 </div>
<div hello dear> 2 </div>
<div hello dear> 3 </div>
<div hello dear> 4 </div>
<div hello dear> 5 </div>
<script>
//module declaration
var app = angular.module("myApp",[]);
//controller declaration
app.controller('myCtrl',function($scope){
    //no code
});
//directives declaration
app.directive('hello',function(){
    return{
        restrict: 'A',
        compile: function(tElement, tAttributes){
            tElement.addClass("red");
            console.log("compiled");
        },
    }
});
app.directive('dear',function(){
    return{
        restrict: 'A',
        link: function($scope, element, attributes){
            element.addClass("blue");
            console.log("linked");
        }
    }
});
</script> 
</body> 
</html>

期望:

编译运行一次。链接运行5次。

结果:

编译和链接运行5次。

屏幕截图:

enter image description here

参考:

http://www.bennadel.com/blog/2794-when-do-you-need-to-compile-a-directive-in-angularjs.htm

有人可以告诉我为什么编译运行5次(或者,如何只运行一次)?

2 个答案:

答案 0 :(得分:1)

编译阶段在每个指令的链接阶段之前,因为您在5个元素上应用了hello指令,它的预期行为要编译然后链接5次。可以在here找到关于指令与子指令的链接过程的更详细说明。

编译功能

当Angular bootstraps时,每个指令的编译函数只被调用一次。

正式地说,这是执行(源)模板操作的地方,不涉及范围或数据绑定。

首先,这是为了优化目的;考虑以下标记:

<tr ng-repeat="raw in raws">
    <my-raw></my-raw>
</tr>

<my-raw>指令将呈现一组特定的DOM标记。所以我们可以:

允许ng-repeat复制源模板(<my-raw>),然后修改每个实例模板的标记(在编译函数之外)。 修改源模板以包含所需的标记(在编译函数中),然后允许ng-repeat复制它。 如果raws集合中有1000个项目,则后一个选项可能比前一个项目更快。

执行:

  • 操纵标记,使其成为实例(克隆)的模板。

不要:

  • 附加事件处理程序。
  • 检查子元素。
  • 设置对属性的观察。
  • 在示波器上设置手表。

答案 1 :(得分:1)

这是预期的行为。 看看https://docs.angularjs.org/api/ng/service/ $ compile

每个指令标记都会发生整个流程(编译,控制器,前/后链接)。

这将使您的编译只运行一次:

<hello>
    <div dear> 1 </div>
    <div dear> 2 </div>
    <div dear> 3 </div>
    <div dear> 4 </div>
    <div dear> 5 </div>
</hello>

虽然在这种情况下,不需要使用编译阶段,只需使用链接

app.directive('hello',function(){
  return{
    restrict: 'AE',
    link: function(scope, iElement){
        iElement.children().addClass("red");
        console.log("\"compiled\"");
    },
  }
});

编辑:如果您需要在亲爱的人之前运行hello指令的代码,请将代码放在预链接而不是链接。

.directive('hello', function() {
  return {
    restrict: 'AE',
    compile: function() {
      return {
        pre: function(scope, iElement) {
          iElement.children().addClass("red");
          console.log("\"compiled\"");
        }
      }
    },
  }
})