为什么角度为在同一 DOM 元素上定义的指令定义“优先级”属性

Why does angular define "priority" property for directives that are defined on the same DOM element?

本文关键字:定义 优先级 属性 指令 元素 DOM 为什么      更新时间:2023-09-26

我发现 angular 没有利用定义指令的顺序,而是使用静态priority字段。它并非适用于所有情况。

例:

<div ng-if="items.length < 50" ng-repeat="item in items"></div>
<div ng-repeat="item in items" ng-if="items.length > 50"></div>

这两行代码可能有不同的含义。

案例1)检查项目数量是否小于50,NG重复10000项目

案例 2) ng-重复 10000 个项目,然后在每个元素上检查项目数量是否小于 50

如果ng-if具有更高的优先级,则第一行代码将允许显然非常重要的优化...

显然,与按定义顺序对指令进行优先级排序相比,使用静态"优先级"字段没有太多理由,所以我的问题是:

应该采取什么步骤来批准这个想法并加以实施?

我从来没有研究过angularjs源代码,需要一些外部帮助来指出需要更改的地方才能提供主题方法,我将感谢在这个方向上的任何外部帮助

提前谢谢你!


编辑

这是一个 jsFiddle 显示ng-if对于 10000 个项目的数组执行了 20000 次,每个ng-if都会创建一个范围,使问题加倍......

http://jsfiddle.net/u840t0dh/17/

我找不到为什么 angular 不利用定义指令的顺序的原因,而不是使用静态优先级字段,它不适合所有情况。

角度指令的想法是扩展浏览器内置的标记语言(标签,属性等)。我相信标准浏览器标记中没有这样的功能。我想强调的是,角度中的指令是声明式编程

对于您指出的问题,在我看来,这就像是命令式编程。这就像您在页面中用ifloop编写逻辑一样。但是在您的情况下,在同一元素上使用它们没有多大意义=>这与在任何命令式编程语言(c ++,c#,java,...)中在同一行上编写iffor loop非常相似。如果你遵循命令式编程的思维方式,这样写会更有意义:

<div ng-if="items.length > 50">
    <div ng-repeat="item in items"></div>
</div>

我同意有时为了编写 UI 渲染代码,我们必须编写有点像命令式编程,但它可以保持在最低限度。即使在这些情况下,如果你遵循命令式编程的思维方式(就像我指出的那样),也不应该有问题。

因此,您指出的问题可能是一个问题,但实际上与我们从声明性标记中获得的优势相比不是一个大问题。

声明式编程和命令式编程各有利弊:

  • http://en.wikipedia.org/wiki/Declarative_programming
  • https://softwareengineering.stackexchange.com/questions/32781/declarative-programming-vs-imperative-programming

对于扩展"标记"的指令的情况,声明式编程更有意义,这是角度指令的设计方式(标记实际上是声明性的)

声明式编程的重点是告诉你想要"什么",而不是"如何"去做。这样做的好处是:它更简单更容易理解。

来自 MSDN

事实上,易于理解代码 — 即使在不熟悉的情况下 上下文 - 是声明式样式的主要优点之一。

声明式编程最显着的好处是程序 指定我们想要获得的"什么"作为结果,而不是"如何"。作为一个 结果,更重要的是了解我们的领域 使用语言的每个细节

有了你的建议,更多的是关于你想"如何"完成一项任务。您的建议的缺点是,当我们使用指令时,我们需要了解它们在"内部"的工作方式。

例如:当你对同一个元素使用许多指令时,使用这些指令的人需要了解放置指令的顺序是什么(这应该是实现指令的人关心的问题)。这是声明式编程试图避免的事情,因为它对于指令的用户来说很复杂

为了回答您的问题,优先级有几个可能的用例。我并不是说它们很常见,但它们是可能的,而且可能非常强大......

下面是两个示例:

用例 A) 包装任何指令。

通过使用优先级,您可以在给定指令之前或之后运行自定义代码。假设您有一个包含数千个 ng-click 指令的现有角度应用程序,并希望在每次 ng-click 之前运行一些东西。你可以做这样的事情:

angular.module('app', [])
.directive('ngClick', function($rootScope) {
  return {
    restrict: 'A',
    priority: 100,
    link: function(scope, element, attr) {
      element.bind('click', function(ev) {
        alert("custom click running");
      })
    }
  }
})
.controller('MyCtrl', function($scope) {
  $scope.alert = function() {
    alert('built-in click running!')
  }
})
<!DOCTYPE html>
<html ng-app="app">
<head>
  <script data-require="angular.js@1.0.7" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
</head>
<body ng-controller="MyCtrl">
  <a ng-click="alert()">Click me</a>
</body>
</html>

在这里,您的自定义单击将在单击的角度构建之前运行。

用例 B) 终止执行

通过使用优先级和终端:true,可以阻止执行其他指令。例如,在所有删除操作上,您可以使用自定义指令来请求确认。在这种情况下,使用 DOM 定义的顺序将是危险的,因为您要删除记录。

var app = angular.module('terminal', []);
app.controller('MainCtrl', function($scope) {
  $scope.deleteIt = function() {
    window.alert('Delete called!');
  }
});
app.directive('confirmationNeeded', function() {
  return {
    priority: 10,
    terminal: true,
    link: function(scope, element, attr) {
      var msg = attr.confirmationNeeded || "Are you sure?";
      var clickAction = attr.ngClick;
      element.bind('click', function() {
        if (window.confirm(msg)) {
          scope.$eval(clickAction)
        }
      });
    }
  };
});
<!doctype html>
<html ng-app="terminal">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
</head>
<body ng-controller="MainCtrl">
  <a href="#" ng-click="deleteIt(id)" confirmation-needed="Are you sure you want to Delete?">Delete with custom message</a>
</body>
</html>