如何解决大内容的角度性能问题

时间:2016-02-13 07:04:21

标签: javascript angularjs performance data-binding

我熟悉角度的摘要周期以及它如何影响长列表和大型模型值的性能。我只是好奇你是否有针对我的案例的问题的任何解决方法。 我正在构建一个应用程序,可能需要也可能不需要用户输入大文本,例如textarea中的错误日志,但是由于与大型模型上的双向数据绑定相关的角度固有问题它导致我的应用程序挂起。

目前我要求用户在文件中附加大量内容。但我想知道是否有办法解决这个问题。 我能想到的一个潜在的解决方法是不在文本字段上使用模型,并使用angular的轻量级jquery api angular.element('#mytext').val()访问文本。但是这种方法的缺点是将JS代码与DOM紧密绑定,这不是一个好习惯。我对更多“棱角分明”的解决方案感兴趣。

这是演示性能问题的plunkr。要查看挂起,请在文本区域中键入内容,然后您将遇到严重的延迟

http://plnkr.co/edit/0wccRJjjlhJqZtdipDLv?p=preview

enter image description here

1 个答案:

答案 0 :(得分:2)

瓶颈不是摘要(可以有效但可以与ngModelOptions 'debounce' option进行有效争斗)但a listener added by textarea directive在元素上使用ng-model时。

Firebug profile

这种性能问题表明使用自定义指令而不是内置指令(在本例中为ngModel)。对于双向绑定,它可能是

app.directive('bigText', function () {
  return {
    scope: {
      bigText: '='
    },
    template: '<textarea>',
    link: function (scope, element) {
      // .val(value) on directive init
      var initialized = false;
      // prevents .val(oldValueFromOutside) on input
      var internalChange = false;
      var $textarea = element.find('textarea');

      scope.$watch('bigText', function (oldVal, newVal) {
        if (internalChange || (initialized && oldVal === newVal)) return;
        initialized = true;
        $textarea.val(newVal);
      });

      // generic JS debounce,
      // for ex. https://github.com/niksy/throttle-debounce
      var handler = debounce(1000, function () {
        var text = $textarea.val();
        if (scope.bigText !== text) {
          internalChange = true;
          scope.$apply(function () {
            scope.bigText = text;
          });
          internalChange = false;
        }
      });
      $textarea.on('change keyup', handler);
      // $textarea.off on scope destroy
    }
  };
});

手动维护双向绑定的重要部分是使用internalChange标志,它可以防止在摘要(鸡/蛋困境)中从外部作用域获取旧值newVal

Angular指令对输入事件for performancecompatibility的处理也可以学到一些东西。

请注意,类似的性能问题可能由Chrome bug引起,而不是由Angular应用程序引起。