让Angular检测$ scope的变化

时间:2015-04-06 05:08:04

标签: javascript angularjs angularjs-directive angularjs-service

我正在编写我的第一个AngularJS应用程序,并且我正在尝试获取一个指令,以便在从服务接收到的数组发生更改时更新其视图。

我的指示如下:

angular.module('Aristotle').directive('ariNotificationCenter', function (Notifications) {
    return {
        replace: true,
        restrict: 'E',
        templateUrl: 'partials/ariNotificationCenter.html',
        controller: function ($scope) {
            $scope.notifications = Notifications.getNotifications();

            $scope.countUnread = function () {
                return Notifications.countUnread();
            };
        }
    };
});

部分很简单:

<p>Unread count: {{countUnread()}}</p>

虽然我的Notifications服务看起来像这样:

function Notification (text, link) {
    this.text = text;
    this.link = link;
    this.read = false;
}

var Notifications = {
    _notifications: [],

    getNotifications: function () {
        return this._notifications;
    },

    countUnread: function () {
        var unreadCount = 0;

        $.each(this._notifications, function (i, notification) {
            !notification.read && ++unreadCount;
        });

        return unreadCount;
    },

    addNotification: function (notification) {
        this._notifications.push(notification);
    }
};

// Simulate notifications being periodically added
setInterval(function () {
    Notifications.addNotification(new Notification(
        'Something happened!',
        '/#/somewhere',
        Math.random() > 0.5
    ));
}, 2000);

angular.module('Aristotle').factory('Notifications', function () {
    return Notifications;
});

getNotifications函数返回对数组的引用,当setInterval被调用时,该引用会被addNotification设置更改。但是,获取视图更新的唯一方法是运行$scope.$apply(),这会因为删除Angular的所有自动方面而发臭。

我做错了什么?

感谢。

2 个答案:

答案 0 :(得分:2)

我认为代码的唯一问题是您使用setInterval更新模型数据,而不是Angular内置服务$ interval。将调用替换为setInterval

$interval(function () {
    Notifications.addNotification(new Notification(
        'Something happened!',
        '/#/somewhere',
        Math.random() > 0.5
    ));
}, 2000);

如果没有你致电$scope.$apply,它应该可行。另请记住在工厂实施$interval中注入Notifications服务。

angular.module('Aristotle').factory('Notifications', function ($interval) {

$interval在内部调用$scope.$apply

答案 1 :(得分:1)

我还不是Angular的专家,但看起来你的问题可能属于偏见。

<p>Unread count: {{countUnread()}}</p>

我认为你无法绑定功能的结果。如果这样做有效,我相信它只会计算一次价值,然后就完成了,这似乎是你所写的问题。

相反,我相信你应该用同一个名字创建一个变量:

$scope.countUnread = 0;

然后用函数更新控制器中的值。

然后,在您的部分中,删除括号。

<p>Unread count: {{countUnread}}</p>

只要$scope.countUnread确实在控制器中更新,更改应该反映在部分中。

作为旁注,如果你采用这种方法,我建议重命名变量或函数,因为这可能会导致问题或至少混淆。