【问题标题】:angular.js: model update doesn't trigger view updateangular.js:模型更新不会触发视图更新
【发布时间】:2013-04-24 07:18:11
【问题描述】:

我目前正在开发基于 Web 的 twitter 客户端,因此我使用了 angular.js、node.js 和 socket.io。我通过 socket.io 将新推文推送到我的客户端,服务等待新推文。当一条新推文到达时,服务会通过 $broadcast 发送一个事件。

在我的控制器中是一个事件监听器,传入的推文正在一个单独的函数中处理。这个函数只是在我的推文范围内推送新推文。

现在,我的问题是,我的观点没有更新,但我可以看到我的范围在扩大。也许你们中的一个人有一个想法,我该如何解决这个问题?

另外我的代码:

服务:

(function () {
    app.factory('Push', ['$rootScope', function ($rootScope) {
        socket.on('new-tweet', function (msg) {
            $rootScope.$broadcast('new-tweet', msg);
        });
    }]);
}());

控制器:

(function () {
    app.controller("StreamCtrl", function StreamCtrl ($scope, $rootScope, $http, Push) {
        $scope.tweets = [];

        $http
            .get('/stream')
            .then(function (res) {
                $scope.tweets = res.data;
            });

        $scope.addTweet = function (data) {
            $scope.tweets.push(data);
            console.log($scope.tweets);
        };

        $rootScope.$on('new-tweet', function (event, data) {
            if (!data.friends) {
                $scope.addTweet(data);
            }
        });
    });
}());

整个项目在这里:https://github.com/hochitom/node-twitter-client

【问题讨论】:

  • 尝试在 addTweet 中添加 $scope.$apply() 并查看视图是否更新

标签: javascript angularjs angularjs-scope


【解决方案1】:

在 addTweet 中添加下面的代码行,问题就解决了

$scope.addTweet = function (data) {
            $scope.tweets.push(data);
            $scope.$apply();
            console.log($scope.tweets);
        };

【讨论】:

  • 谢谢。 $scope.$apply() 帮助了我。只是好奇-这是更新视图的正确方法吗?意思是,角度不应该“决定”范围已经改变吗?
  • 这是一个很好的问题,jimhoskins.com/2012/12/17/angularjs-and-apply.html Jim Hoskins 对为什么在这种情况下需要apply 有一个很好的总结。
  • 非常感谢您的回答。 $scope.$apply() 为我工作。我曾经使用 $injector.invoke(...) 动态设置控制器。但无法在视图上更新 $scope 变量。 $scope 变量仅在按键或模糊时更新,但是当我使用 $scope.$apply() 时,$scope 变量在页面最初加载时立即在视图上更新。非常感谢。
【解决方案2】:

我更喜欢使用$timeout(不要忘记将其注入您的控制器)而不是$apply

 app.controller("StreamCtrl", function StreamCtrl ($scope, $timeout $rootScope, $http, Push) {

    //...

    $scope.addTweet = function (data) {
        $timeout(function() {
            $scope.tweets.push(data);
            console.log($scope.tweets);
        });
    };

    //...

});

【讨论】: