Ember.js 在Emberjs中为销毁前的视图设置动画
目前没有办法延迟在灰烬中查看销毁。 如果要在销毁视图之前设置视图动画,则会出现问题 因此,我目前有一个非常丑陋的解决方法:Ember.js 在Emberjs中为销毁前的视图设置动画,ember.js,Ember.js,目前没有办法延迟在灰烬中查看销毁。 如果要在销毁视图之前设置视图动画,则会出现问题 因此,我目前有一个非常丑陋的解决方法: willDestroyElement: -> $clone = @$().clone().addClass "animate-destruction" @$().parents(':first').prepend $clone setTimeout -> $clone.off().remove() , 350 注意:动画是在css中的.
willDestroyElement: ->
$clone = @$().clone().addClass "animate-destruction"
@$().parents(':first').prepend $clone
setTimeout ->
$clone.off().remove()
, 350
注意:动画是在css中的.animate destruction
类中完成的
我知道我的方法不好,所以我想知道是否有人想出了更好的方法。这只是我自己自发的想法: 这是Ember.View()中destroyElement的实现: 您可以尝试覆盖此方法来制作动画:
destroyElement: function() {
var completeCallback = function(){
return this.currentState.destroyElement(this);
}
this.$().fadeOut(completeCallback); //or whatever animation
},
试试这个
Ember.Route.extend({
actions: {
willTransition: function(transition) {
$.each(Ember.View.views, function(index, value) {
var popUpView = value.get('classNames').find(function(item) {
return item == '[nameofyourclass]';
});
if(!Em.isEmpty(popUpView) && value.get('visible')) {
value.set('visible', false);
value.get('controller').set('previousTransition', transition);
transition.abort();
}
});
return true;
},
}
});
Ember.View.extend({
classNames: ['nameofyourclass'],
classNameBindings: ['visible:element-visible'],
visible: false,
didInsertElement: function() {
var t = this,
controller = this.get('controller');
this.$()
.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function() {
if(!t.get('visible')) {
var previousTransition = controller.get('previousTransition');
if(!Em.isEmpty(previousTransition)) {
controller.set('previousTransition', null);
previousTransition.retry();
} else { // fallback
controller.transitionToRoute('index');
}
}
});
Em.run.next(this, function() {
this.set('visible', true);
});
},
});
我处理预销毁动画的首选方法是使用
Em.Evented
。让视图侦听在方法或操作中调用的事件,该方法或操作将开始销毁视图,并延迟销毁,直到事件触发的方法完成(使用运行循环)。例如:
SomeView = Em.View.extend({
_listen: function() {
this.get('controller').on('closeChildView', this, this.hide);
}.on('willInsertElement'),
hide: function() {
this.$().fadeOut(this.get('controller.duration'));
}
});
然后在控制器中:
Em.ObjectController.extend(
Em.Evented, { // Important mixin!
duration: 500,
actions: {
removeSomeChildView: function() {
this.trigger('closeChildView');
Em.run.later(this, function() {
// Then do the stuff to destroy the view here.
}, this.get('duration'));
}
}
});
或者,您可以在视图中使用this.removeFromParent()
方法来合并视图的隐藏和删除
如果销毁实际上是在视图本身中启动的,则可以在调用销毁方法之前使用这些相同的原则,并在删除视图后需要回调时,使用.on('willDestroyElement')
向控制器或路由发送操作
通过在didInsertElement
上运行this.$().hide
,然后使用show()
方法转换视图元素,可以以相同的方式完成预销毁动画
调整JS和CSS转换时间
如果您在CSS中进行一些转换,那么您需要确保CSS和JS之间的转换时间是一致的。这很简单。在您的视图中,确保CSS转换发生在视图的元素上,然后:
SomeView = Em.View.extend({
transitionDuration: Em.computed.alias('controller.transitionDuration'),
setTransitionDuration: function() {
var ms = parseFloat(this.$().css('transition-duration')) * 1000; // In milliseconds
if (ms) {
this.set('transitionTime', ms);
}
}.on('didInsertElement'),
});
这将更新视图和控制器上的转换持续时间,以匹配您在CSS中编写的内容。在控制器上为
transitionDuration
指定的任何值都是transitionDuration
的回退值,如果您想在覆盖默认JStransitionDuration之前进行一些验证,可以在上述方法中添加if()
,这实际上是我的第一个想法,直到我试过。我发现它不起作用,因为在阅读视图销毁代码(主要是willDestroy
回调)后,我发现:destroy元素
很少在视图上被调用来销毁实际的DOM元素,因为通常是父视图的元素被删除,而destroyElement
仅为了回调而对子级调用(DOM元素实际上已被父级删除)。您的视图通常是子视图。还有其他原因,如在使用{{outlet}}
时,新视图会以其他方式替换它…相关:
SomeView = Em.View.extend({
transitionDuration: Em.computed.alias('controller.transitionDuration'),
setTransitionDuration: function() {
var ms = parseFloat(this.$().css('transition-duration')) * 1000; // In milliseconds
if (ms) {
this.set('transitionTime', ms);
}
}.on('didInsertElement'),
});