Подтвердить что ты не робот

Как ускорить приложение AngularJS?

У меня есть приложение AngularJS со страничной сеткой (два вложенных ng-repeat). На одной странице имеется примерно 25x40 элементов ввода. В начале, который сделал 1000 привязок, производительность пейджинга была приемлемой.

Но тогда сложность страницы растет: динамические классы, различные контекстные меню, условный контент для каждой ячейки сетки. И с оценкой 6000 привязок (6 на каждый элемент ввода) пейджинг стал непригодным для использования.

Мой вопрос: как я вообще подхожу к проблемам производительности в AngularJS? Очевидным первым шагом является измерение. Но результаты Chrome Profiler не говорят мне об этом, далеко не зная, как действовать.

 Self      Total                           Function
-----------------------------------------------------------------
24 ms    2.79 s    angular.js:7997         Scope.$digest
 1 ms       1 ms   controllers.js:365      setViewportData
16 ms     692 ms   angular.js:13968        ngRepeatWatch
 8 ms      22 ms   angular.js:6439         extend.literal
 9 ms    1.22 s    angular.js:14268        ngSwitchWatchAction
16 ms      45 ms   angular.js:12436        ngModelWatch
 0        621 ms   angular-ui-4.0.js:264   initDateWidget
 0         13 ms   angular.js:12859        ngClassWatchAction
 0         70 ms   angular.js:14184        ngStyleWatchAction
 1 ms       5 ms   angular-ui-4.0.js:261   getOptions
 0         16 ms   angular.js:579          copy
 0          1 ms   angular.js:4558         interpolateFnWatchAction
 1 ms       2 ms   angular.js:5981         token.fn.extend.assign
 0         37 ms   angular.js:8151         Scope.$eval
 1 ms       1 ms   angular.js:6137         extend.constant
14 ms      16 ms   angular.js:651          equals
 1 ms       1 ms   angular.js:4939         $interpolate.fn

Кроме того, есть ли вероятность, что "Object.observe()" ускорит работу в будущем (игнорируя "initDateWidget", это, очевидно, другая тема)?

4b9b3361

Ответ 1

То, что вы можете сделать, ускорит ваше приложение Angular, самое главное - уменьшить эти привязки, где вы можете. Один из способов сделать это - создать директиву, которая построила таблицу для вас с помощью DOM-манипуляции вместо использования ng-повторов. Это уменьшит количество общих часов, которые вы должны обработать, и сделайте этот дайджест намного быстрее.

Я знаю, что это уродливо, но Angular не предназначено для установки более 3000 привязок. Поскольку он делает дайджест, и это не шаблон наблюдателя, он действительно замедляет работу, поэтому многие настроены.

Вы даже можете использовать гибридный подход, в котором вы все еще использовали ng-repeat, но все значения были помещены в DOM с прямой обработкой DOM из пользовательской директивы, что позволило избежать всех привязок.

Ответ 2

Если вы этого еще не сделали, установите модуль AngularJS Chrome Batarang, который поможет вам определить, какое из ваших привязок вызывает у вас горе. https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en

Как следует из другого ответа, то, что вы ищете, вероятно, является небольшим случаем установки бесконечного прокрутки для вашей таблицы, где модель, с которой вы связываете, является подмножеством, отображаемым на экране.

Компонент ng-grid реализует это и может стоить взглянуть на то, чтобы использовать его напрямую или украсть технику. http://angular-ui.github.com/ng-grid/

Ответ 3

Ресурс

Этот пост о производительности angularJS в больших списках имеет хороший обзор параметров, которые вы имеете для настройки производительности.

Выше ответы (кроме плагина Batarang) также упоминаются внутри. Это всего лишь обзор советов в этой статье.

Уменьшить данные с помощью limitTo (разбиение на страницы)

Одно из наиболее очевидных решений - уменьшить количество привязок, уменьшив количество элементов в вашем представлении. Разбиение данных может производиться с помощью фильтра limitTo на ng-repeat.

Пример Как повысить производительность ngRepeat над огромным набором данных (angular.js)? В этой статье также есть пример jsbin, связанный.

Также не забудьте использовать встроенный метод для предоставления данных, так как это будет оцениваться на каждом $digest.

<li ng-repeat="item in filteredItems()"> // Bad idea, since very often evaluated.
<li ng-repeat="item in items"> // Way to go! 

Удалить привязки с помощью bindonce

Еще одно очевидное решение - удалить привязки для определенных элементов. Конечно, это означает, что обновления больше не будут отображаться в представлении.

Решение bindonce делает гораздо больше, чем просто удаление привязки в 2 способа. В основном он ожидает, что значение будет привязано один раз до удаления привязки. Лучше всего читайте сами. Подробнее см. проект bindonce.

В приведенной выше статье есть также информация о шаблоне, работающем с 2 списками. Один для визуализации и один как источник данных.

Использовать ng-сетку

Ng-grid имеет то преимущество, что он отображает только те элементы, которые в настоящее время видны. Подробнее на http://angular-ui.github.io/ng-grid/.

Аналогичный ng-if полностью удаляет скрытые элементы из дерева DOM, а ng-show сохраняет их только на месте, но скрыт. Примите во внимание, что ng-if поместит копию оригинала (оригинал - это ключ, а не те изменения), который появился, когда он будет показан снова.

Советы по фильтрации

В статье также есть несколько полезных советов для фильтрации списков.

Как и использование ng-show, чтобы скрыть отфильтрованные элементы, так как этот способ не может быть создан подстроем.

И еще один метод, называемый "debounce user input". Последняя опция - подождать с фильтрацией, пока пользователь не перестанет печатать. Включая пример jsfiddle.

Подробнее

Дополнительные советы можно найти в связанной статье. Там есть ресурсы, которые должны быть хорошей отправной точкой. Я считаю, что самые очевидные и быстрые победы перечислены здесь.

Еще одна приятная запись Как работает привязка данных в AngularJS?

Ответ 4

Немного поздно, но, возможно, это сработает для вас:

https://github.com/Pasvaz/bindonce

Вы можете использовать его в тех привязках, которые не предназначены для изменения, поэтому $digest больше не будет обрабатывать их.

Ответ 5

В angular 1.3 и более вы можете связать один раз, используя:: не нужно использовать другие 3-сторонние js

<li ng-repeat="item in :: items">

Это хорошо, если элементы не будут меняться, поэтому вы можете связать их один раз

Ответ 6

Я столкнулся с проблемами производительности, когда количество слушателей превысило 1000+ в компоненте сетки данных.

Я решил эти проблемы, используя директиву, которая строит мое представление с помощью response.js. директива выставила функцию обновления.

каждый раз, когда данные изменялись (в контроллере), функция обновления вызывала директиву, а затем механизм реакции .js эффективно выполнял рендеринг.

Я знаю его большие накладные расходы, чтобы использовать вторую основную структуру внутри проекта angular, и это не настоящая манера связывания данных. но его работа намного быстрее.

В конце концов я прекратил использование angular.js и перешел на response.js + FLUX. я думаю, что это лучше, но я знаю, что его нелегко перейти от angular, но это того стоит.

Angular директива, которая использует response.js

Ответ 8

У меня были проблемы с производительностью с ng-сетью с большими данными, она была решена путем замены Angular Grid. Демо на этом сайте показывает, что он легко управляет 100 000 строк.

Ответ 9

Я боролся с этим несколько недель. Я обнаружил, что две вещи существенно изменили:

(i) ОДНОВРЕМЕННЫЕ РАЗМЕРЫ: используйте одноразовые привязки, где вы можете; а также (ii) DEBOUNCE: для ввода, который мне не нужен, сразу же размножается, но может ждать 250 мс, установите настройку debounce. Это сделало НЕВЕРОЯТНОЕ отличие от моей большой таблицы ng-repeat. Я не могу подчеркнуть, насколько эффективна настройка debounce. (см. здесь https://docs.angularjs.org/api/ng/directive/ngModelOptions)

Ответ 10

bject.observe() - это предлагаемый механизм для передачи истинной привязки данных к браузеру. Он предоставляет механизм наблюдения за изменениями объектов и массивов, уведомляя других о мутациях, сделанных для этих объектов.

<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<title>Object.observe()</title>

<link rel="stylesheet" href="../css/main.css" />

</head>

<body>

<div id="container">

  <h1><a href="https://shailendrapathakbits.wordpress.com/" title="code_lab_by_shail ">code_lab_by_shail</a> Object.observe()</h1>

    <p>An object <code>o</code> is created and <code>Object.observe()</code> is called on it.</p>

  <p>Three changes are made to <code>o</code> and <code>Object.observe()</code> records these changes as shown below.</p>

  <p>Use the console to find out what happens if you make further changes to <code>o</code>: it defined in global scope.</p>

  <p>Call <code>Object.unobserve(o, observer)</code> to stop observing changes.</p>

  <p id="data" style="font-size: 14px;"></p>

  <script src="js/main.js"></script>

  <a href="https://github.com/shailendra9/objectobserver/blob/master/index.html" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>

</div>

<script src="../js/lib/ga.js"></script>

</body>
</html>