【问题标题】:Animating views before destruction in Emberjs在 Emberjs 中销毁之前的动画视图
【发布时间】:2013-02-26 15:14:43
【问题描述】:

目前无法在 Ember 中延迟视图销毁。 如果您想在销毁视图之前对其进行动画处理,则会出现问题。

所以,我目前有这个极其丑陋的解决方法:

willDestroyElement: ->
  $clone = @$().clone().addClass "animate-destruction"
  @$().parents(':first').prepend $clone
  setTimeout ->
    $clone.off().remove()
  , 350

注意:动画是在 css 中的 .animate-destruction 类中完成的。

我知道我的方法不好,所以我想知道是否有人提出了更好的方法。

【问题讨论】:

标签: ember.js


【解决方案1】:

这只是我的一个自发想法:

这是 Ember.View (Link to Source) 中 destroyElement 的实现:

 destroyElement: function() {
    return this.currentState.destroyElement(this);
  },

您可以尝试重写此方法来制作动画:

destroyElement: function() {
    var completeCallback = function(){
        return this.currentState.destroyElement(this);
    }
    this.$().fadeOut(completeCallback); //or whatever animation
},

【讨论】:

  • 这实际上是我的第一个想法,直到我尝试过。我发现它不起作用,因为在阅读了视图销毁代码(主要是 willDestroy 回调)后,我发现了这一点:destroyElement 很少在视图上调用以销毁实际的 DOM 元素,因为通常它是父视图的元素被删除,并且 destroyElement 仅出于回调的原因在子级上调用(DOM 元素实际上已被父级删除)。您的视图通常是子视图。还有其他原因,比如在使用{{outlet}}时,无论如何都会被新视图取代...
【解决方案2】:

试试这个

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);
    });
},
});

【讨论】:

    【解决方案3】:

    我首选的处理预销毁动画的方法是使用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() 方法来合并视图的隐藏和移除。

    如果销毁实际上是在视图本身中开始的,您可以在调用destroy方法之前使用这些相同的原则,并使用.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 的后备值,如果您想在覆盖默认JS transitionDuration 之前进行一些验证,您可以在上述方法中添加if ()

    【讨论】:

      猜你喜欢
      • 2014-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 2015-09-08
      相关资源
      最近更新 更多