angular-ui-路由器视图的控制器是否会导致 $scope.$watch 不触发?

Do controllers of angular-ui-router views cause $scope.$watch not to fire?

要解释这个问题,请看下面的内容states

.state('app.play.lobby', {
            url: '/lobby',
            resolve: {
                games: function (FirebaseAdapter) {
                    return FirebaseAdapter
                        .syncArray('disciplines')
                        .$loaded()
                        .then(function (list) {
                            return list;
                        });
                },
                tournaments: function (FirebaseAdapter) {
                    return FirebaseAdapter
                        .syncArray('tournaments')
                        .$loaded()
                        .then(function (list) {
                            return list;
                        });
                }
            },
            views: {
                filter: {
                    templateUrl: 'play/lobby/filter.tpl.html',
                    controller: LobbyFilterController
                },
                browser: {
                    templateUrl: 'play/lobby/browser.tpl.html',
                    controller: LobbyBrowserController
                }
            }
        });

一切正常。问题是:在控制器 LobbyFilterController 中,我正在使用 $scope.$watch() 来监听对象的变化。但是 $watch() 命令仅触发一次,即在状态成功加载后 。一旦状态被加载并且我更改了对象内部属性的值,没有任何反应。

LobbyFilterController

function LobbyFilterController($scope, games, TournamentFilter) {
    $scope.filter = {
        game: null,
        mode: 'regular',
        type: 'all',
        format: 'all',
        eliminationMode: 'all',
        gridsize: 'all',
        status: 'all',
        groupstage: false,
        reshuffledGrid: false,
        password: false
    };

    $scope.$watch($scope.filter, function(data) {
        console.log('filter changed...');
    }, true);
}

当我尝试使用 $scope.myVar 等正常值时,此行为没有改变。由于事件在加载后触发一次,我想我没有犯错(希望我错了)?

您需要将 属性(或 watch expression)作为字符串或 return 是一个值的函数表达式提供。相反,您正在设置一个对象。尝试将其更改为:

$scope.$watch('filter', function(data) {
    console.log('filter changed...');
}, true);

$watch 使用 $parse to create a getter out of the provided expression. And what you have provided is an object as expression which will just get ignored as it looks for only string or function. Look at the case statements at the source。并且所有观察者将至少触发一次以在摘要循环期间启动脏检查,这在您的情况下也会发生,如果您在第一次执行中查找参数,您将看到两个值都是未定义的,因为没有真正观察到的东西或者观察者总是会 return undefined 覆盖 angular.noop 函数。