AngularJS:$ scope.array.push()不会更新视图,即使使用$ apply也是如此

时间:2014-06-29 01:02:09

标签: angularjs angularjs-scope angularjs-ng-repeat angularjs-controller

我正在尝试学习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,sinceId和count之前已初始化,我没有把它放在那里,因为我觉得不重要。

2 个答案:

答案 0 :(得分:10)

如果Angular的NgRepeat多次迭代相同的对象,那么麻烦似乎就会停止。我要created a jsFiddle进行演示。

在第一部分中,您可以向数组添加字符串。第一个按钮总是添加相同的字符串对象,而第二个按钮每次都创建一个新的字符串对象。请注意,只要您单击第一个按钮两次,添加到列表中的内容就不重要了。

在第二部分中,我们总是添加一个新对象,即使这些对象都包含对同一字符串对象的引用。这可以按照您的预期工作。

因此,为了使其成为明确的答案,请确保添加到列表中的内容是 distinct 对象,并在需要时使用对象文字来强制执行此操作。我希望Array#push超过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 :(得分:6)

我相信如果你构建你的ng-repeat(使用$ index跟踪),它就不会停止在dupes上:

<div class='tweet' ng-repeat='p in posts track by $index'>
...
</div>