我在我的 Angular 应用程序中使用 angular 1.6.5 并遇到了一个非常奇怪的行为。
我想要实现的是:当 ngroute 被更改时,我必须从当前 View 中删除事件类,等待离开动画完成,然后将事件类添加到新 View 。
我已经在配置中设置了应用程序和路由。
var app = angular.module('app', ['ngAnimate', 'ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl:"home.html",
reloadOnSearch:false
})
.when('/about-us', {
templateUrl:"about.html",
reloadOnSearch:false
})
.when('/contact', {
templateUrl:"contact.html",
reloadOnSearch:false
})
.otherwise({
template : "<h1>None</h1><p>Nothing has been selected</p>"
});
});
我有一项服务,我存储动画时间和 bool 值,指示 View 的可见性:
app.service('animationProperties', function () {
this.animationTimings = {
views: 1000
};
this.visibility = {
view : false
};
});
我有一个具有简单调试功能的主 Controller 和一个 onRouteChangeStart 函数,它应该从当前 View 中删除事件类(通过使 View 可见性 bool 值为 false):
app.controller('MainCtrl', function ($scope, $window, $location,
animationProperties) {
$scope.animationProperties = animationProperties;
$scope.$on('$routeChangeStart',function () {
animationProperties.visibility.view = false;
});
$scope.toggleActive = function(){
$scope.animationProperties.visibility.view = !$scope.animationProperties.visibility.view;
}
});
最后一件事,等待离开动画完成的 ngAnimate,然后删除当前 View (使用 done() 方法)并通过将可见性 bool 值设为 true 再次进入新 View :
app.animation('.view', function($timeout, animationProperties) {
return {
enter: function(element, done) {
$timeout(function () {
animationProperties.visibility.view = true;
$timeout(function () {
done();
}, animationProperties.animationTimings.views);//Wait to enter
},animationProperties.animationTimings.views); //Wait for leave function
},
leave: function(element, done) {
$timeout(function () {
done();
}, animationProperties.animationTimings.views);
}
}
});
这里是 plunker
第一次(从导航)切换页面时,您会看到一切正常,但是当第二次转到页面时, View 类没有更新,因此没有播放动画。在调试时,您可以清楚地看到可见性 bool 值已正确更新,但离开 View 时的 ng-class 未得到更新。
您的帮助将不胜感激!!!
最佳答案
引用我自己来自 here :
这是正在发生的事情:
$routeChangeStart
,您更改(一旦评估)将告诉 ngClass
的值删除 active
从离开的 Angular 上课。 $route
开始准备进入 View ,包括获取它的模板。 $routeChangeSuccess
事件,它发出信号 ngView
开始交换两个 View 。 ngView
破坏离开 View 的作用域,从那时起作用域的观察者不再被……观察。 因此,如果步骤 1-4 发生得足够快,则在为
ngClass
评估必要的表达式之前,将破坏离开 View 的范围。删除 active
类(class)。第一次访问路线时,动画有效,因为 $route
必须对进入 View 的模板发出服务器请求(这给了ngClass
时间来完成它的工作)。但是,当您访问之前访问过的路线时,模板已经被缓存并且过渡很快。您可以通过故意减慢模板检索速度来解决此问题(即使是虚拟机轮次也足够了)。例如:
app.decorator('$templateRequest', ($delegate, $timeout) => {
const $templateRequest = (...args) => $delegate(...args).
then(tmpl => $timeout().then(() => tmpl));
Object.defineProperty($templateRequest, 'totalPendingRequests', {
get: () => $delegate.totalPendingRequests,
set: nv => $delegate.totalPendingRequests = nv,
});
return $templateRequest;
});
(Updated plnkr 1)
另一种解决方法是实现您自己的、简单的、同步版本的
ngClass
。 ,以便在离开 View 的范围被销毁之前立即应用类。此类指令的粗略、未优化、非生产就绪版本可能如下所示:app.directive('myClass', () => (scope, elem, attrs) => {
scope.$watchCollection(attrs.myClass, newValue => {
Object.keys(newValue).forEach(c => {
if (newValue[c]) {
elem.addClass(c);
} else {
elem.removeClass(c);
}
});
});
});
(Updated plnkr 2)
话虽如此,您的设置似乎很奇怪:
$routeChangeStart
)。 animationProperties.visibility.views
的标志 ( ngClass
)删除一个类。 animation('.view')
) 与 CSS 动画同步,然后设置标志。 😕
对于初学者,为什么同时使用 CSS 和 JS 动画?例如,您可以处理 JS 动画的不透明度变化(假设您的实际设置更复杂,并且需要 JS 动画来获得其他效果)。
或者,您可以使用基于自动添加/删除的纯 CSS 动画更轻松地处理淡入/淡出
ng-enter
/ng-leave
类(它只是 4 个微小的 CSS 规则 :smiley :):[ng-view].ng-enter {
/* Wait for the leaving view to...leave, then start transitioning in. */
transition: opacity 1s ease 1s;
}
[ng-view].ng-leave {
/* Start transitioning out. */
transition: opacity 1s ease;
}
[ng-view].ng-enter,
[ng-view].ng-leave.ng-leave-active {
/*
* At the beginning of the entering animation and
* at the end of the leaving animation,
* the view must be fully invisible.
*/
opacity: 0;
}
[ng-view].ng-enter.ng-enter-active,
[ng-view].ng-leave {
/*
* At the end of the entering animation and
* at the beginning of the leaving animation,
* the view must be fully visible.
*/
opacity: 1;
}
(Updated plnkr 3)
关于javascript - Angular 未在 ng-view 上更新 ng-class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46365402/