javascript - 在 AngularJS 中重新执行指令时出现渲染速度问题

标签 javascript angularjs angularjs-directive

我有以下简单的基本指令:

angular.module("base", [])
  .directive("base", function() {
    return {
      restrict: "A",
      scope: true,
      controller: function($scope) {
        this.setHeader = function(header) {
          $scope.header = header;
        }
        this.setBody = function(body) {
          $scope.body = body;
        }
        this.setFooter = function(footer) {
          $scope.footer = footer;
        }
      },
      templateUrl: "base.html"
    }
  });

我通过以下方式将数据传递给该指令:

 .directive("custom", function() {
    return {
      restrict: "E",
      require: "^base",
      scope: {
        ngModel: "="
      },
      link: function($scope, $element, $attrs, baseCtrl) {
        //Do something with the data or not...
        baseCtrl.setHeader($scope.ngModel.header);
        baseCtrl.setBody($scope.ngModel.body);
        baseCtrl.setFooter($scope.ngModel.footer);
      }
    }
  });

当我创建 custom 指令列表时,我注意到 custom 指令不会立即呈现。我做了一个Plunker demonstrating这种行为。 (您将看到列表单元格瞬间为空,然后指令将出现)

此设计背后的目标是重用 base 指令的模板,并仅传递显示所需的数据。在这个简单的示例中, $scope.data 正是我需要传入的内容,但可能需要先发生一些规则或操作。我不想让查询数据的 Controller 处理这个问题,而是想将其传递到指令中,从而分离关注点。

所以我的问题是:

  1. 有什么方法可以使指令渲染速度更快并避免 Plunker 中显示的闪烁吗? ?
  2. 这是在 Angular 中重用指令的最佳实践吗?

最佳答案

闪烁是由对 "base.html" 文件的异步 http 请求引起的。由于 base 指令的 HTML 必须从服务器加载,因此在一小部分时间内不会显示任何内容。

为了渲染数据,Angular 将经历以下 3 个阶段:

  1. 从服务器获取 HTML 文件/模板(不会显示任何内容)
  2. 编译 HTML 模板(DOM 已更新,但范围尚未链接)
  3. 将范围链接到 DOM/模板(显示预期数据)

选项 1 - 使用template 属性

只需将 templateUrl: "base.html" 替换为直接 HTML 内容即可:

//templateUrl: "base.html"
template: '<div class="base"><div class="header bottom-border"><h2>{{header}}</h2><div><div class="body bottom-border"><p>{{body}}</p></div><div class="footer">{{footer}}</div></div>',

您会注意到这次不会有任何闪烁(检查此 plunker )。

选项 2 - 预加载模板文件

Angular 有一个内置模板缓存 ( $templateCache ),用于检查是否已从服务器获取任何 HTML 模板文件/内容。如果您在应用程序加载时填充该缓存,那么 Angular 将不需要获取模板来渲染指令,它将直接从缓存中读取它。

您可以使用 Angular 的 $templateRequest (如果您使用的是 Angular 的最新测试版)或 $templateCache (对于任何版本)。 不同之处在于 $templateRequest 自动发出 HTTP GET 请求并将结果存储在 $templateCache 中。另一方面,您必须手动执行此操作,如下所示:

loadTemplate = function(tpl) {
  $http.get(tpl, { cache : $templateCache })
    .then(function(response) {
      $templateCache.put(tpl, html);
      return html;
    });
};
loadTemplate('base.html');

但请注意,此方法需要您的应用程序有一个“加载阶段”。


关于重用指令的最佳实践,您似乎走在正确的道路上。这个例子太简单了,无法提供任何建议......不过,请检查此 Angular "Creating Custom Directives" 中的“最佳实践”注释指南。

编辑

(我的个人关于模板的偏好templateUrl)

如果主要目标仅仅是性能(即页面渲染速度),那么模板似乎是最佳选择。获取一个文件总是比获取两个文件更快...但是,随着应用程序的增长,必须需要良好的结构,而模板文件是最佳实践之一。

通常我遵循这个“规则”:

  1. 如果模板中只有几行 HTML,则只需使用 template
  2. 如果 HTML 模板不会随时间不断变化(即帖子结构、联系方式等),请使用 template,否则(即包含横幅/广告的模板)请使用 模板网址
  3. 如果应用有加载阶段,请使用带有缓存的 templateUrl

关于javascript - 在 AngularJS 中重新执行指令时出现渲染速度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25587704/

相关文章:

php - 物理仪表板/状态板的库和伪代码

javascript - 当用户点击另一个显示输入标签时,如何自动点击隐藏的提交输入标签?

html - 如何将 REST 响应放回 angular JS 标签中以绘制 D3 js 饼图

javascript - 在 AngularJS Controller 和指令中使用 "this"而不是 "scope"

javascript - 如何在 Angular 中通过 $resource 从自定义指令发送输入值?

javascript - $.each 函数不迭代

javascript - 在java脚本中更改函数内对象的属性值无法正常工作

javascript - AngularJS - 表单验证,如何滚动到第一个无效输入

解析对象时AngularJS插值错误

angularjs - AngularJS 中的 ng-app V/S 数据-ng-app