2016-01-27 2 views
5

Я пытаюсь отфильтровать некоторые каналы в зависимости от выбранной категории.ng - если вызывается больше раз, чем должно

У меня есть нг-повторение channel in channels, который имеет ng-if="hasCategory(channel.category)

Вот документ:

db.channels.find().pretty() 
{ 
    "_id" : "2kj9GK8jE9yHezoWb", 
    "name" : "example name", 
    "logo" : "path/to/image.svg", 
    "number" : 2, 
    "category" : [ 
     "Broadcast", 
     "Premium" 
    ], 
    "tags" : "example tag tags" 
} 

Это функция обрабатывать нг-если:

$scope.hasCategory = function (categoryNameArray) { 
    console.log('thisisbeingcalled'); 
    var e = _.indexOf(categoryNameArray, $scope.activeCategory); 
    if (e === -1) { 
    return false; 
    } else { 
    return true; 
    } 
}; 

и это то, как я устанавливаю активную категорию:

$scope.setCategory = function (name) { 
    $scope.activeCategory = name; 
}; 

, которые я посылаю, нажав на кнопку в окне:

<section layout="row" layout-align="center center" layout-wrap ng-init="activeIndex; activeCategory"> 
    <md-button flex="auto" flex-sm="45" flex-xs="100" ng-repeat="kit in kits | orderBy: 'order'" ng-class="{active: (activeIndex.index == $index)}" class="md-raised"> 
    <a href="" ng-click="activeIndex.index = $index; setCategory(kit.name);" class="bold">{{kit.name}}</a> 
    </md-button> 
</section> 

вот наборы документ схемы:

db.kits.find().pretty() 
{ "_id" : "k7JFX6DHu5GYnyer3", "name" : "Broadcast", "order" : 1 } 
{ "_id" : "KrKRm4gysw5sfQnnr", "name" : "Premium", "order" : 2 } 
{ "_id" : "dieukQ3NRsA44CSns", "name" : "Ultimate", "order" : 3 } 

Теперь у меня есть только один канал, чтобы проверить это, но каждый раз, когда я нажимаю кнопка для изменения категории, функция $scope.hasCategory вызывается несколько раз даже при запуске страницы (первая загрузка времени)

enter image description here

У меня также есть панель поиска для поиска каналов в текущей категории, я не уверен, что это влияет и на это.

<input type="text" ng-model="queryname" ng-model-options="{debounce: 500}"> 

Теперь это становится действительно лагом, когда у меня есть более чем 100 каналов, нг-если вызывается более чем 10k раза, что делает страницу замораживания довольно долгое время.

Что я могу сделать, чтобы исправить эту проблему?

EDIT

Забыл добавить, где ng-if был:

<md-card flex="15" flex-xs="40" class="slide-up" layout="column" ng-repeat="channel in channels | orderBy: 'number' | filter: queryname" ng-if="hasCategory(channel.category)" ng-init="channel.edit = false"> 
    <md-card-header ng-show="channel.edit == false"> 
    <img ng-src="{{channel.logo}}" alt=""> 
    </md-card-header> 
    <md-card-header-text ng-show="channel.edit == false"> 
    <span class="md-subhead dark-blue" layout="row" layout-align="center" layout-margin>{{channel.number}}</span> 
    </md-card-header-text> 
</md-card> 

ответ

6

Ваш ng-if будет называться на каждом переваривать цикле. Проблема состоит в том, что он содержит выражение, включающее вызов функции. Угловое не имеет возможности узнать, когда результат выражения может измениться, поэтому он называет его каждый раз.

Лучшим вариантом было бы установить флаг в каждом из каналов и использовать ng - если нужно просто проверить соответствующий флаг. Затем вам просто нужно обновлять флаги при изменении $scope.activeCategory, которые вы можете либо сделать с кодом, в котором вы устанавливаете категорию, либо с помощью $scope.$watch(), чтобы запускать его автоматически.

например.

$scope.setCategory = function (name) { 
    $scope.activeCategory = name; 
    for (var index=0; index < $scope.channels.length; index++) { 
     $scope.channels[index].hasCategory = hasCategory($scope.channels[index].category, name); 
    } 
}; 

function hasCategory(categoryNameArray, name) { 
    console.log('thisisbeingcalled'); 
    var e = _.indexOf(categoryNameArray, name); 
    if (e === -1) { 
    return false; 
    } else { 
    return true; 
    } 
} 

Затем в шаблоне:

<md-card flex="15" flex-xs="40" class="slide-up" layout="column" 
    ng-repeat="channel in channels | orderBy: 'number' | filter: queryname" 
    ng-if="channel.hasCategory" 
    ng-init="channel.edit = false"> 
    <md-card-header ng-show="channel.edit == false"> 
    <img ng-src="{{channel.logo}}" alt=""> 
    </md-card-header> 
    <md-card-header-text ng-show="channel.edit == false"> 
    <span class="md-subhead dark-blue" layout="row" layout-align="center" layout-margin>{{channel.number}}</span> 
    </md-card-header-text> 
</md-card> 

должно быть более эффективным.

+0

ahh, большое вам спасибо! Я сделал некоторые изменения к вашему коду, как '$ scope.channels [index].hasCategory = hasCategory ($ scope.channels [index] .category, name); 'и теперь это работает, еще один вопрос заключается в том, как установить стартовую категорию, чтобы пользователю не нужно было выбирать категорию для просмотра каналов , –

+0

в вашем методе hasCategory(). Вы должны изменить возвращаемое значение на 'return! (E === -1)'. Это более читаемо – Riverside

+0

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