事件监听器的指令优先级

时间:2015-07-28 17:59:41

标签: javascript angularjs events angularjs-directive angularjs-compile

我有一个带2个指令的输入元素:
-direc(优先级1)
-directive(优先级0)

即使首先执行 direc 指令也会先执行。
为什么?

这是一个显示正在发生的事情的片段

angular.module('app', [])


.directive('direc', function(){
  
  return {
    priority : 1,
    link : function(scope, element){
      
      element.on('click', function(){
          alert('direc');
      });
    
    }
  };  

})

.directive('directive', function(){
  
  return {
    priority : 0,
    link : function(scope, element){
      
      element.on('click', function(){
          alert('directive');
      });
    
    }
  };  

});
<div ng-app="app">

   <input type="text" direc directive/>

</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

2 个答案:

答案 0 :(得分:2)

基本上当指令进入图片时会发生什么,angular首先运行指令compile函数。

compile中,您可以控制原始DOM / plain DOM,在compile函数中,您将没有范围。编译函数负责返回preLinkpostLink函数。其中preLink首先被调用

preLink函数内部,您可以使用范围内的DOM,在preLink之后,它会渲染内部元素或其他指令。遍历该DOM的每个元素后,它将触发postLink函数。其中纯粹使用范围编译DOM。这就是为什么directive事件首先被注册,因为它具有最低优先级并具有其功能postLink

Plunkr for Understanding Flow(查看控制台以使其更清晰)

您应该在preLink函数中注册这些事件,以便在执行编译指令函数后注册事件。

<强>代码

angular.module('app', [])
.directive('direc', function() {
  return {
    priority: 1,
    compile: function(element, attributes) {
      console.log("Compiled direc")
      return {
        pre: function(scope, element, attrs) {
          console.log("Prelink for direc firective generated");
          element.on('click', function() {
            alert('direc');
          });
        },
        post: function(scope, element, attrs) {
          console.log("Called After direc DOM linked with scope")
        }
      }
    },
  }
})
.directive('directive', function() {
  return {
    priority: 0,
    compile: function(element, attributes) {
      console.log("Compiled direc")
      return {
        pre: function(scope, element, attrs) {
          console.log("Prelink for direc firective generated");
          element.on('click', function() {
            alert('directive');
          });
        },
        post: function(scope, element, attrs) {
          console.log("Called After directive DOM linked with scope")
        }
      }
    },
  };
});

Working Plunkr

答案 1 :(得分:1)

根据文档:

  

当在单个DOM元素上定义了多个指令时,有时需要指定应用指令的顺序。 优先级用于在编译函数调用之前对指令进行排序。优先级定义为数字。首先编译具有更高数字优先级的指令。预链接功能也按优先级顺序运行,但后链接功能以相反的顺序运行。具有相同优先级的指令的顺序是未定义的。默认优先级为0。

我认为你混淆了优先级的功能,因为它与首先调用哪个指令的事件监听器无关,而是首先运行它们的链接函数。

如果在执行链接功能时对元素进行了更改,您可以看到区别:

angular.module('app', [])
.directive('direc', function(){

  return {
    priority : 1,
    link : function(scope, element){
      element.html('direc with priority 1');

      element.on('click', function(){
        alert('direc');
      });

    }
  };  

})

.directive('directive', function(){

  return {
    priority : 0,
    link : function(scope, element){
      element.html('directive with priority 0');

      element.on('click', function(){
        alert('directive');
      });

    }
  };  

});

优先级最低的元素是最后一个要运行的元素,因此生成的HTML是“direc with priority 1”

这是一个有效的傻瓜:http://plnkr.co/edit/VKqiMQDyMFsFguuRp7Ko?p=preview