AngularJS' $ watch'更改值时不会触发

时间:2015-12-05 16:15:59

标签: javascript angularjs watch angularjs-watch angular-digest

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

为此,我创建了一个检查innerWidthinnderHeight的函数,如果宽度大于高度那么快乐的日子。这在我加载页面时非常有效,但我也会在resize事件被触发时检查方向。

所以我的代码流程是 -

  1. 触发resize事件调用$scope.getOrienttion()
  2. 计算当前方向并返回结果
  3. 使用$scope.getOrienttion()监控对watch值的更改,并更新$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,具体取决于$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>
    

2 个答案:

答案 0 :(得分:2)

虽然从getOrientation事件中调用resize只执行getOrientation代码,但它并没有暗示某些事情发生了变化。因此,您需要通过$apply()调用$scope来告诉角度运行摘要周期。在调用摘要周期后,angular将评估所有$watcher,并且您的观察者函数将被评估。

实际上,来自getOrientation事件的resize方法调用似乎没有执行与范围级别绑定相关的任何操作。因此,您可以从那里删除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.
});

答案 1 :(得分:1)

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

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

    }, false);