【问题标题】:$watch not updating when service object is updated更新服务对象时 $watch 不更新
【发布时间】:2015-11-10 14:16:52
【问题描述】:

我发现了一个令人困惑的情况,其中 $scope.watch 没有像我预期的那样触发。我希望你们中的一些 AngularJS 爱好者可以帮助阐明为什么 Angular 对 $scope.watch 和 Service 对象的行为如此特殊。请注意,这是在我弄乱 Ionic 框架时发现的。

以下是我正在运行的示例,它按预期工作(用于在会话期间维护状态信息。)

TL;DR: 当我在服务中使用新的 userObject (currentUser = new userObject();) 更新 currentUser 时,Watch 不会在控制器上触发。如果我改为更新对象的每个单独属性,它确实会触发。

currentUser.name = 'Foo'; 
currentUser.email = 'foo@bar.com';

我正在寻求有关原因的指导,以便更好地理解。

代码

服务(工作)

angular.module('app.services')
.service( 'UserService', function() {
    var userObject = function(){
        return {
            id: null,
            username: null,
            email: null,
            fullName: null,
            modified: null
        }
    };
    var currentUser = new userObject();

    var createUser = function(id, username, email, fullName, modified ){
        var newUserObject = new userObject();
        newUserObject.id = id;
        newUserObject.username = username;
        newUserObject.email = email;
        newUserObject.fullName = fullName;
        newUserObject.modified = (modified) ? modified : new Date();
        return newUserObject;
    };

    var setCurrentUser = function(userObj){
        console.log('First');
        console.dir(currentUser);

        setUserId(userObj.id);
        setUsername(userObj.username);
        setEmail(userObj.email);
        setFullName(userObj.fullName);         
        setModifiedDate(userObj.modified);

        console.log('Second');
        console.dir(currentUser);

        return currentUser;
    };

});

控制器

angular.module('app.controllers')
.controller('DashboardCtrl', function ($scope, UserService) {
    var dashboard = this;

    dashboard.user = UserService.currentUser;

    $scope.$watch('UserService.currentUser', function(newVal, oldVal) {
        if (newVal !== oldVal ){
            dashboard.user = newVal;
        }
    });

    var createdUser = UserService.createUser(
        1,
        'user1',
        'asdf@asdf.com',
        'Test User',
        new Date()
    );
    UserService.setCurrentUser(createdUser);
});

查看

<div ng-controller="DashboardCtrl as dashboard">
    <span bind="dashboard.user.fullName">Loading</span>
</div>

结果

哇哦!加载在初始化时被替换为 ''(null),并在手表更新后立即使用 'Test User' (比人眼快,除非调试)

中断场景

上面的代码效果很好。但是,我想尝试通过创建一个新的 UserObject 然后将该对象设置为“当前用户”来减少重复工作来减少代码。我所做的更改如下(视图和控制器不变):

服务(损坏)

angular.module('app.services')
.service( 'UserService', function() {
    var userObject = function(){
        return {
            id: null,
            username: null,
            email: null,
            fullName: null,
            modified: null
        }
    };
    var currentUser = new userObject();

    var createUser = function(id, username, email, fullName, modified ){
        var newUserObject = new userObject();
        newUserObject.id = id;
        newUserObject.username = username;
        newUserObject.email = email;
        newUserObject.fullName = fullName;
        newUserObject.modified = (modified) ? modified : new Date();
        return newUserObject;
    };

    var setCurrentUser = function(userObj){
        console.log('First');
        console.dir(currentUser);

        // Set original 'currentUser' with a new UserObject passed by controller
        currentUser = userObj;            

        console.log('Second');
        console.dir(currentUser);

        return currentUser;
    };

});

结果

在 init (null) 上加载被替换为 '' 并且 $scope.watch 在这种情况下永远不会触发。我的期望是手表应该对对象进行深入观察,当我用新对象替换对象时,它应该触发对象发生变化并触发手表。

我唯一能想到的是,当我用新对象替换 currentUser 对象时,$watch 的委托也会在该对象上丢失。有没有人知道我如何分辨?

呸。

【问题讨论】:

    标签: angularjs angularjs-service angularjs-controller angularjs-watch


    【解决方案1】:

    当您向$watch 提供字符串时,它会检查角度函数内的变量,因为您的范围内没有UserService.currentUser,那么该观察程序函数将永远不会被触发。

    为了让您的手表正常工作,您需要使用函数而不是string,然后该函数将返回一个表达式。通过将其添加到 watcher 函数中,以便在每个摘要周期对其进行评估并执行脏检查。如果值发生变化,它将触发观察者函数

    代码

    $scope.$watch(function(){
       return UserService.currentUser;
    }, function(newVal, oldVal) {
        if (newVal !== oldVal ){
            dashboard.user = newVal;
        }
    });
    

    【讨论】:

    • 但是由于除了当前用户在服务中的更新方式之外没有任何改变,不确定这将如何影响结果。我会试一试并更新它,看看它的调用方式是否会改变它的行为方式,同时监视完全替换的对象。
    • 更新:使用函数方法代替字符串不起作用,因为问题似乎是服务没有触发监视事件(当对象被替换为一个新的。当您更新单个属性时,它可以完美运行,这就是我如此困惑的原因)
    猜你喜欢
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多