我在我的 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
从离开 View 中删除active
类的值。 $route
开始准备进入的 View ,包括获取其模板。 $routeChangeSuccess
事件,该事件指示ngView
开始交换两个 View 。 ngView
破坏了离开 View 的范围,从此以后,该范围的观察者就不再受到监视。 因此,如果步骤1-4发生得足够快,则在评估必要的
ngClass
表达式以删除active
类之前,将离开 View 的范围被破坏。第一次访问路线时,动画会起作用,因为$route
必须向输入 View 的模板发出服务器请求(这使ngClass
有时间完成其工作)。但是,当您访问以前访问的路线时,模板已经被缓存,并且转换速度很快。您可以通过故意减慢模板检索的速度来解决此问题(即使VM转弯就足够了)。例如:
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动画才能具有其他效果)。
或者,您可以基于自动添加/删除的
ng-enter
/ng-leave
类的纯CSS动画,更轻松地处理淡入/淡出(这只是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/