AngularJS“$watch”在值更改时不触发

AngularJS '$watch' not firing when value is changed

我有一个必须以横向模式查看的网络应用程序。

为此,我创建了一个检查 innerWidthinnderHeight 的函数,如果宽度大于高度,那么祝你好运。这在我加载页面时非常有效,但我还可以在触发 resize 事件时检查方向。

所以我的代码流程是-

  1. 触发 resize 事件调用 $scope.getOrienttion()
  2. 计算当前方向和return结果
  3. 使用 watch 监视对 $scope.getOrienttion() 值的更改并更新 $scope.orientation
  4. 的值

上面的第 1 步和第 2 步似乎工作正常,但我的 watch 从未检测到对 $scope.getOrienttion() 的更改,并且仅在页面加载时触发。我一定是做错了什么,谁能帮我找出问题所在。

这里是相关的AngularJS-

christmasApp.controller('bodyCtrl', function($scope, $window){

    angular.element($window).bind('resize', function(){
        console.log('Event triggered');
        $scope.getOrientation();
    });

    $scope.getOrientation = function(){

        var w = $window.innerWidth,
            h = $window.innerHeight;
        var orientation = (w > h) ? 'landscape' : 'portrait'
        console.log('Function triggered - ' + orientation)
        return (w > h) ? 'landscape' : 'portrait';

    };

    $scope.$watch($scope.getOrientation, function(newValue, oldValue){
        $scope.orientation = newValue;
        console.log('Watch triggered - ' + newValue);
    }, true);

});

这里是 HTML 有条件 class 集,取决于 $scope.orientation 的值(可能不相关,但以防万一)-

<body <?php body_class(); ?> data-ng-controller="bodyCtrl">

    <div id="orientationMask" data-ng-class="{visible: orientation != 'landscape'}">
        <p>Please turn your device to the <b>landscape</b> orientation.</p>
    </div>

    { Additional code, obscured by the mask if it is show... }

</body>

虽然从 resize 事件调用 getOrientation 只是执行 getOrientation 代码,但它并不暗示 angular 某些事情已经发生变化。所以你需要在 $scope 上调用 $apply() 来告诉 angular 运行 摘要周期。在调用摘要循环后 angular 将评估所有 $watchers 并且你的观察者函数将被评估。

实际上,来自 resize 事件的 getOrientation 方法调用似乎没有做任何与范围级别绑定相关的事情。所以你可以从那里删除 getOrientation 方法,因为它似乎调用了一个在那里什么都不做的代码。

代码

angular.element($window).bind('resize', function(){
    console.log('Event triggered');
    $scope.getOrientation(); //you could remove this method, as its not modifying any scope
    //will run digest cycle, and the watcher expression will get evaluated
    $scope.$apply(); //you could also use $timeout(function(){}) here run safe digest cycle.
});

你为什么不像这样听 orientationchange 事件呢?

    window.addEventListener("orientationchange", function() {
            switch(window.orientation){  
            case -90:
            case 90:
                $rootScope.orientation = "landscape";
                break; 
            default:
                $rootScope.orientation = "portrait";
            break; 
            };

    }, false);