#angularjs #angularjs-scope #angularjs-ng-repeat #angularjs-controller
#angularjs #angularjs-scope #angularjs-ng-repeat #angularjs-контроллер
Вопрос:
Я пытаюсь изучить AngularJS, и есть одна вещь, которую я не понимаю, которая кажется, что весь интернет решается с помощью $scope.$apply
, но я уже использую его, и он ничего не делает.
В принципе, я использую Twitter API для получения временной шкалы, и когда мы прокручиваем снизу, он загружает больше твитов. Эта часть работает, я использую фабрику для этого, но я могу отобразить полученный объект в консоли, у меня здесь нет проблем.
У меня есть такой вид, чтобы отображать данные:
<div class='timeline' ng-controller='TimelineCtrl' is-scrolled='loadData()'>
<div class='tweet' ng-repeat='p in posts'>
<img class='portrait' src='{{p.user.profile_image_url}}' />
<p>{{p.text}}</p>
<p class='date'>{{p.created_at}}</p>
</div>
</div>
Мой контроллер выглядит так:
$scope.posts = [];
// Load the original tweets list
TwitterAPI.timeline($scope.count, function(data) {
$scope.$apply(function() {
$scope.maxId = data[data.length-1].id;
$scope.sinceId = data[0].id;
$scope.posts.push(data);
});
});
данные являются законными.
То, что я вообще не понимаю, и заставляет меня думать, что это очень легко решить, и я просто не вижу этого, заключается в том, что если я использую ‘= data’ вместо ‘push (data)’, представление обновляется. Даже когда я загружаю больше твитов, если я использую ‘=’, представление обновляется (с заменой содержимого, конечно, что не то, что я хочу).
Примечание: MaxID, поскольку ID и count инициализированы ранее, я не помещал их туда, поскольку не думаю, что это имеет значение.
Комментарии:
1. Я не верю, что вы можете использовать
Array.push()
этот способ. Попробуйтеconcat
вместо этого:$scope.posts.concat(data);
2. Вау, так много времени на это, и это потому, что я не знаю свой 101. Это то, что на 100% мне нужно было использовать
$scope.posts = $scope.posts.concat(data)
для объединения обоих массивов. Спасибо, чувак.3. Посмотрите этот пример . Похоже, они используют Array#push, и, похоже, это работает.
4. Также
Array.prototype.push.apply($scope.posts, data)
работает, поскольку данные представляют собой массив, вы хотите добавить их все, не добавляя массив данных как отдельный элемент в массив posts .
Ответ №1:
Проблема, похоже, в том, что Angular NgRepeat
останавливается, если он повторяет один и тот же объект более одного раза. Я создал jsFiddle для демонстрации.
В первом разделе вы можете добавлять строки в массив. Первая кнопка всегда добавляет один и тот же строковый объект, в то время как вторая каждый раз создает новый строковый объект. Обратите внимание, что как только вы дважды нажмете первую кнопку, не имеет значения, что вы добавляете в список.
Во втором разделе мы всегда добавляем новый объект, даже если все эти объекты содержат ссылку на один и тот же объект string . Это работает так, как и следовало ожидать.
Итак, чтобы сделать это явным ответом, убедитесь, что вещи, которые вы добавляете в свой список, являются отдельными объектами, и используйте объектные литералы для обеспечения этого, если это необходимо. Я бы предпочел Array#push
over Array#concat
, потому что последний каждый раз создает новый объект массива, и если у вас много элементов, это приведет к большому оттоку и большой сборке мусора.
HTML-код:
<div ng-controller="Controller1">
<button ng-click="addLine()">Add Line</button>
<button ng-click="addNumber()">Add Number</button>
<button ng-click="reset()">Reset</button>
<div>{{lines}}</div>
<div ng-repeat="line in lines">
{{line}}
</div>
</div>
<hr />
<div ng-controller="Controller2">
<button ng-click="addObject()">Add Object</button>
<button ng-click="reset()">Reset</button>
<div>{{objects}}</div>
<div ng-repeat="obj in objects">
{{obj.data}}
</div>
</div>
JavaScript:
(function () {
var myApp = angular.module('myApp', []);
myApp.controller('Controller1', function ($scope) {
$scope.lines = [];
$scope.addLine = function () {
$scope.lines.push('Hello world!');
};
$scope.addNumber = function () {
$scope.lines.push('Line ' $scope.lines.length);
};
$scope.reset = function () {
$scope.lines = [];
};
});
myApp.controller('Controller2', function ($scope) {
$scope.objects = [];
$scope.addObject = function () {
var obj = { data: 'Hello world!' };
$scope.objects.push(obj);
};
$scope.reset = function () {
$scope.objects = [];
};
});
})();
Комментарии:
1. Спасибо, Крис, что произойдет, если вам нужно обновить существующий элемент массива? Например, список мог измениться на сервере, и вы хотите удалить его и обновить массив как новыми отдельными элементами, так и обновленными существующими.
Ответ №2:
Я считаю, что если вы структурируете свой ng-repeat как таковой (с отслеживанием по $index), он не остановится на дубликатах:
<div class='tweet' ng-repeat='p in posts track by $index'>
...
</div>