AngularJS: ng-repeat против $interpolate

Из того, что я видел в Angular 2.0, я чувствую, что некоторое время буду использовать Angular 1.x. В нем есть все строительные блоки, которые, я думаю, мне нужны, единственный недостаток в том, что у него есть проблема с производительностью из-за грязной проверки, поэтому я пытаюсь думать об этом больше. Теперь ng-repeat может стать проблемой из-за количества добавляемых наблюдателей.

Итак, у меня есть эта часть шаблона (в нефрите):

li(ng-repeat='topMenuItem in sideMenu.topMenu', ng-class='{"is-active": topMenuItem.display === sideMenu.activeTopMenu}')
  a(href='{{ topMenuItem.href }}') {{ topMenuItem.display }}
    ul(ng-if='sideMenu.secondMenu.length > 0 && topMenuItem.display === sideMenu.activeTopMenu')
      li(ng-repeat='secondMenuItem in sideMenu.secondMenu', ng-class='{"is-active": secondMenuItem.display === sideMenu.activeSecondMenu}')
        a(href='{{ secondMenuItem.href }}') {{ secondMenuItem.display }}

Когда отображается 22 пункта меню, количество наблюдателей составляет 90 (используя этот фрагмент закладки).

Я решил поэкспериментировать с попыткой использовать $interpolate для создания этого меню. Я закончил с директивой с этим для функции компиляции:

compile: function(element, attributes) {
  var topLevelExpression = $interpolate('<li{{ cssClass }}><a href="{{ topMenuItem.href }}">{{ topMenuItem.display }}</a>{{ secondLevelMenuHtml }}</li>');
  var secondLevelExpression = $interpolate('<li{{ cssClass }}><a href="{{ secondMenuItem.href }}">{{ secondMenuItem.display }}</a></li>');

  var updateMenu = function() {
    var html = '';

    sideMenu.topMenu.forEach(function(topMenuItem) {
      var cssClass = topMenuItem.display === sideMenu.activeTopMenu ? ' class="is-active"': '';
      var secondLevelMenuHtml = '';

      if(sideMenu.secondMenu.length > 0 && topMenuItem.display === sideMenu.activeTopMenu) {
        secondLevelMenuHtml += '<ul>';

        sideMenu.secondMenu.forEach(function(secondMenuItem) {

          var cssClass = secondMenuItem.display === sideMenu.activeSecondMenu ? ' class="is-active"': '';
          secondLevelMenuHtml += secondLevelExpression({
            secondMenuItem: secondMenuItem,
            cssClass: cssClass,
          });
        });

        secondLevelMenuHtml += '</ul>';
      }

      html += topLevelExpression({
        topMenuItem: topMenuItem,
        cssClass: cssClass,
        secondLevelMenuHtml: secondLevelMenuHtml
      });
    });

    element.find('.application-navigation').html(html);
  };

  return function($scope) {
    $scope.$watchCollection('sideMenu', function() {
      updateMenu();
    });
  }
}

Из моего тестирования этот код функционирует точно так же, как и ng-repeat, вывод выглядит так, как должен. Эта версия имеет только 16 наблюдателей, и это число не увеличивается, когда отображается больше элементов, чем ng-repeat.

Поскольку этот код выполняет только тот минимум, который необходим для работы этого фрагмента кода, я думаю, что сам javascript столь же эффективен (если не более эффективен), чем код, который выполняется для ng-repeat.

Это предположение верно?

Есть ли какие-либо проблемы с циклическим созданием DOM таким образом по сравнению с использованием ng-repeat?

1 ответ

Вопрос на засыпку.

Сначала я подумал, что если вы один раз привязываете свойство объекта, то если объект изменился, свойства будут связаны заново.

<div>{{::menu.menuItem}}</div>
<button ng-click="changeMenu()">switch</div>

Это НЕ тот случай.

Что можно сделать, хотя - хотя и с немного странным / хакерским подходом (возможно, в комментариях может быть предложен лучший подход) - это заставить Angular выполнить повторную привязку. Одним из таких кандидатов является ng-if:

<div ng-if="bound">
  <div>{{::menu.menuItem1}}</div>
  <div>{{::menu.menuItem2}}</div>
</div>
<button ng-click="changeMenu()">Switch</div>

Затем в контроллере:

$scope.bound = true;
$scope.menu = {..}; // menu 1
$scope.changeMenu = function(){
  $scope.menu = {..}; // menu 2
  $scope.bound = false;
  $timeout(function(){$scope.bound = true;}, 0);
}

Plunker

Другие вопросы по тегам