我有一个父作用域和一个子作用域,每个作用域都有带有 ng-class="some-class: boolean"的标签。子作用域变量在点击函数中设置为“true”。父项在 .$on 函数中设置为“真”。当 .$on 被触发时,变量会按预期设置为“true”,但它不会将类名应用于标签。
真正奇怪的是,当子作用域的变量设置为 true 时,它会将正确的类应用于两个元素。变量是完全不同的名称,类也是如此。
我做错了什么?
Controller
var app = angular.module('profileApp', []);
app.controller('ProfileController', ['$scope', function($scope){
$scope.contentVisible = false;
$scope.$on('animationEnd', function(){
$scope.contentVisible = true;
});
}]);
//DIRECTIVES
app.directive('introSection', function(){
return {
restrict: 'E',
templateUrl: 'templates/intro-section.html',
controller: function($scope){
$('#cityOutline svg').one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
$scope.$emit('animationEnd');
});
}
}
});
app.directive('experienceSection', function(){
return {
restrict: 'E',
templateUrl: 'templates/experience-section.html',
controller: function($scope){
$scope.toggleDetails = false;
$scope.showDetails = function(){
$scope.toggleDetails = true;
};
$scope.hideDetails = function(){
$scope.toggleDetails = false;
};
}
}
});
HTML
<html lang="en" ng-app="profileApp">
<head>
<script src="js/lib/angular.js" type="text/javascript"></script>
<script src="js/controllers/profileController.js" type="text/javascript"></script>
</head>
<body ng-controller="ProfileController">
<header id="nav" ng-class="{'visible': contentVisible}">
</header>
<experience-section>
<div id="project-details" ng-class="{'open': toggleDetails}">
<button type="button" class="close" ng-click="hideDetails()">X</button>
</div>
<button type="button" class="flat-button" ng-click="showDetails()">View Details</button>
</experience-section>
最佳答案
好的,这是一个常见的错误。为了知道范围内的事物何时发生变化,angular 需要运行一个摘要循环来对范围内的所有内容进行脏检查,然后可以通知 View 它们需要更新。 (如果您想了解更多信息,请参阅官方文档:https://docs.angularjs.org/guide/scope)
通常,您几乎不必担心摘要周期,angular 会自动为您完成……只要您留在 angular 的“世界”中。当我说 Angular 的世界时,我指的是 Angular 的 DOM 事件绑定(bind)之一(如 ng-click
、ng-change
、ng-touch
.. .) 和 $timeout
服务。
在您的情况下,当您这样做时:
$('#cityOutline svg').one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
$scope.$emit('animationEnd');
});
不幸的是,你已经不在 Angular 的世界里了。这意味着当您发出“animationEnd”事件时(即使您使用 Angular 的助手 $on 和 $emit 发出它) Angular 摘要循环也不会被触发并且 Angular 不知道该值已更改,因此它无法更新 View 。
因此在您的情况下,解决方案只是在 $scope.$emit()
之后调用 $scope.$apply();
。这样你就可以强制 Angular 检查是否有任何变化。
所以你的代码看起来像这样:
$('#cityOutline svg').one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
$scope.$emit('animationEnd');
$scope.$apply();
});
下面是当您单击“关闭”按钮时出现的奇怪行为:
- animationEnd 事件被触发(显然是由 jQuery 触发的);
- 您的代码更新范围的值;
- angular 现在没有检测到那个变化,因为没有调用摘要循环;
- 您点击关闭按钮;
- 您的代码更新了其他作用域的值;
- 现在 Angular 正在运行它的摘要周期;
- 它检测到(刚刚)这两个值已经改变;
- 然后它告诉 View 事情发生了变化,它们需要更新。
因此 View 仅在 ng-click 发生后更新,这就是为什么在您单击时应用这两个类的原因。
希望对你有帮助:)
关于javascript - ng-class 绑定(bind)到子作用域中的不同变量而不是分配的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33597876/