#angularjs
#angularjs
Вопрос:
Я изучаю некоторые основы angularjs, и я случайно наткнулся на шаблон, который работает, но я не уверен, почему. Также не уверен, делаю ли я это в духе «angular best practices». Этот пример значительно упрощен по сравнению с тем, над чем я действительно работаю, но общая концепция та же: настройка видимости дочерних элементов на основе переключения на родительском
Моему наивному, наивному я кажется, что он должен каким-то образом наблюдать за функциями, которые используют toggledGroups
массив, а затем ???. Условие ng-show
действительно работает, я просто не совсем понимаю, почему ng-show="isToggled(group)"
оно переоценивается, поскольку массив, который я изменяю, не включен $scope
.
-
Все ли функции, которые существуют в
$scope
, переоцениваются при каждом$digest
? Если это так, мне кажется, что это может создать узкое место дляng-repeats
больших наборов данных. -
Как я упоминал выше, является ли это приемлемым шаблоном или есть лучший / «более угловой» способ, которым я должен думать об этом взаимодействии?
JS:
var app = angular.module('demo', []);
app.service('TransportationService', function(){
var groups = [{
group: "planes",
items: ["Airbus A300", "Extra 300S", "Stearman"]
}, {
group: "trains",
items: ["Flying Scotsman", "The Rocket", "Silver Streak"]
}, {
group: "automobiles",
items: ["Veyron", "Vanquish", "FF", "Continental GT"]
}];
return {
groups: groups
}
});
app.controller('TransportationController', ['$scope', 'TransportationService', function($scope, ts){
var toggledGroups = [];
function isToggled(group) {
return toggledGroups.indexOf(group) > -1;
}
function toggleGroup(group) {
var index = toggledGroups.indexOf(group);
if (index > -1) {
toggledGroups.splice(index, 1);
} else {
toggledGroups.push(group);
}
}
$scope.groups = ts.groups;
$scope.isToggled = isToggled;
$scope.toggleGroup = toggleGroup;
}]);
HTML:
<div ng-app="demo" ng-controller="TransportationController">
<div ng-repeat="group in groups">
<h3>{{group.group}}</h3>
<button ng-click="toggleGroup(group)">Toggle</button>
<ul ng-show="isToggled(group)">
<li ng-repeat="item in group.items">{{item}}</li>
</ul>
</div>
</div>
Скрипка: http://jsfiddle.net/wpHZg/1 /
Комментарии:
1. К какому условному оператору вы имеете в виду, который повторно вычисляется?
2. the
isToggled(group)
. Извините, я плохо сформулировал это3. Я поставил какую-то консоль. журнал внутри функции isToggled, заметил, что каждый раз он вызывает его 6 раз странно…
4. Вы правы. Все свойства в $scope просматриваются и оцениваются. isToggled (group) будет повторно оцениваться при нажатии кнопки, поскольку он пытается повторно отобразить представление. Есть несколько вещей, которые вы можете сделать, чтобы сделать его немного лучше, хотя и не связанных с вашим вопросом. Смотрите скрипку здесь — jsfiddle.net/jain208/wpHZg/6 . Во-первых, я заменил ng-show на ng-if , что немного более эффективно, чем ng-show, плюс элемент не занимает места в DOM. Во-вторых, я упростил ваш метод ToggleGroup, добавив свойство isVisible для group .
5. @mcpDESIGNS: я тоже это заметил. Как в моей демонстрации, так и в моем реальном приложении
isToggled
функция вызывается дважды для каждого рендеринга (34 элемента, 68 вызовов на рендеринг). Происходит с обоимиng-if
иng-show
Ответ №1:
Ваши предположения верны. Каждый раз, когда запускается цикл дайджеста, он выполняет эту функцию. Вы также правы в том, что это дороже. Насколько дороже? Зависит от размера вашего набора данных. Исходя из логики, которую вы показываете, я не могу представить, что это будет слишком сложно для процессора, но вы должны учитывать тот факт, что это будет накладываться на всю другую логику вашего приложения. Насколько я понимаю, вы могли бы предпринять 2 действия, чтобы уменьшить нагрузку на клиентский процессор.
1) легко: добавьте переключаемое свойство в свои группы:
$scope.toggleGroup = function(group) {
group.toggled = !group.toggled
};
<ul ng-if="group.toggled"></ul>
2) Более сложный: допускает некоторую сухость, создайте директиву! : D
app.directive('toggler', function() {
return {
restrict: 'A',
link: function(scope, elem) {
elem.find('.button-toggler').on('click', function() {
elem.find('.togglee').toggle();
});
}
};
});
<div toggler="">
<button class="button-toggler">Toggle Me Hard!</button>
<ul class="togglee" style="display:none"></ul>
</div>
Второй вариант позволяет вам легко переносить вашу директиву в другие части вашего кода. Он также не запустит цикл дайджеста, поскольку он полностью основан на jQuery (что в данном случае хорошо, потому что вы не меняете какие-либо данные области при нажатии). В любом случае у вас будет более чистое приложение.
Комментарии:
1. Также не забудьте использовать
track by
в вашемng-repeat
s. Это уменьшает количество повторных отображений, которые приложение выполняет в DOM.2. Кроме того, по возможности используйте ng-if вместо ng-show .
3. Это правда, @AbhishekJain
4.
track by
иng-if
может внести огромные улучшения, согласованные!5. @Mike: мне нужно будет посмотреть
track by
иng-if
. Я не знал об этом. Спасибо!