AngularJS“$watch”在值更改时不触发
AngularJS '$watch' not firing when value is changed
我有一个必须以横向模式查看的网络应用程序。
为此,我创建了一个检查 innerWidth
和 innderHeight
的函数,如果宽度大于高度,那么祝你好运。这在我加载页面时非常有效,但我还可以在触发 resize
事件时检查方向。
所以我的代码流程是-
- 触发
resize
事件调用 $scope.getOrienttion()
- 计算当前方向和return结果
- 使用
watch
监视对 $scope.getOrienttion()
值的更改并更新 $scope.orientation
的值
上面的第 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 将评估所有 $watcher
s 并且你的观察者函数将被评估。
实际上,来自 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);
我有一个必须以横向模式查看的网络应用程序。
为此,我创建了一个检查 innerWidth
和 innderHeight
的函数,如果宽度大于高度,那么祝你好运。这在我加载页面时非常有效,但我还可以在触发 resize
事件时检查方向。
所以我的代码流程是-
- 触发
resize
事件调用$scope.getOrienttion()
- 计算当前方向和return结果
- 使用
watch
监视对$scope.getOrienttion()
值的更改并更新$scope.orientation
的值
上面的第 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 将评估所有 $watcher
s 并且你的观察者函数将被评估。
实际上,来自 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);