如何*不*在Ember.js中退出路由时销毁View [英] How *not* to destroy View when exiting a route in Ember.js

查看:125
本文介绍了如何*不*在Ember.js中退出路由时销毁View的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于新的Ember.js路由系统( here ),如果我理解正确,当您退出路线时会被破坏。

Regarding the new Ember.js routing system (described here), if I understand correctly, views are destroyed when you exit a route.

在退出路由时是否有任何方式绕过视图的破坏,以便在用户重新进入路由时保留视图的状态?

Is there any way to bypass destruction of views upon exiting a route, so that the state of the view is preserved when the user re-enters the route?

更新:看起来,视图不会被销毁,除非在新路线中更换插座视图。例如,如果您在某些{{outlet master}}中使用ViewA的stateA,并且在{{outlet master}}中使用ViewB进入stateB,则ViewB将替换ViewA。这样做的一个方法是在需要保留视图时定义多个出口,例如{{outlet master1}},{{outlet master2}},...

Update: Looks like, views are not destroyed unless the outlet view is being replaced in the new route. For e.g., if you are in stateA with ViewA in some {{outlet master}} and you go to stateB with ViewB in {{outlet master}}, then ViewB will replace ViewA. A way around this is to define multiple outlets when you need to preserve views, e.g., {{outlet master1}}, {{outlet master2}}, ...

一个很好的功能是将视图数组传递到插座。也可以选择视图是否会被消除,或者在退出路由时被隐藏。

A nice feature would be the ability to pass an array of views to the outlet. And also be able to choose whether views will be destroyed or just become hidden, upon exiting a route.

推荐答案

如何修改路由系统,使插入插座的视图不会被破坏。首先,我覆盖Handlebars 出口帮助器,以便将 Ember.OutletView 加载到 { {出口}}

I have since figure out how to modify the routing system, so that views inserted into outlets are not destroyed. First I override the Handlebars outlet helper, so that it loads an Ember.OutletView into {{outlet}}:

Ember.Handlebars.registerHelper('outlet', function(property, options) {
  if (property && property.data && property.data.isRenderData) {
    options = property;
    property = 'view';
  }

  options.hash.currentViewBinding = "controller." + property;

  return Ember.Handlebars.helpers.view.call(this, Ember.OutletView, options);
});

其中 Ember.OutletView extends Ember.ContainerView 如下:

Where Ember.OutletView extends Ember.ContainerView as follows:

Ember.OutletView = Ember.ContainerView.extend({
    childViews: [],

    _currentViewWillChange: Ember.beforeObserver( function() {
        var childViews = this.get('childViews');

            // Instead of removing currentView, just hide all childViews
            childViews.setEach('isVisible', false);

    }, 'currentView'),

    _currentViewDidChange: Ember.observer( function() {
        var childViews = this.get('childViews'),
            currentView = this.get('currentView');

        if (currentView) {
            // Check if currentView is already within childViews array
            // TODO: test
            var alreadyPresent = childViews.find( function(child) {
               if (Ember.View.isEqual(currentView, child, [])) {          
                   return true;
               } 
            });

            if (!!alreadyPresent) {
                alreadyPresent.set('isVisible', true);
            } else {
                childViews.pushObject(currentView);
            }
        }
    }, 'currentView')

});

基本上我们覆盖 _currentViewWillChange()隐藏所有 childViews 而不是删除 currentView 。然后在 _currentViewDidChange()中,检查 currentView 是否已经在 childViews 并相应地采取行动。 Ember.View.isEqual 下划线 isEqual

Basically we override _currentViewWillChange() and just hide all childViews instead of removing the currentView. Then in _currentViewDidChange() we check if the currentView is already inside childViews and act accordingly. The Ember.View.isEqual is a modified version of Underscore isEqual:

Ember.View.reopenClass({ 
    isEqual: function(a, b, stack) {
        // Identical objects are equal. `0 === -0`, but they aren't identical.
        // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
        if (a === b) return a !== 0 || 1 / a == 1 / b;
        // A strict comparison is necessary because `null == undefined`.
        if (a == null || b == null) return a === b;
        // Unwrap any wrapped objects.
        if (a._chain) a = a._wrapped;
        if (b._chain) b = b._wrapped;
        // Compare `[[Class]]` names.
        var className = toString.call(a);
        if (className != toString.call(b)) return false;

        if (typeof a != 'object' || typeof b != 'object') return false;
        // Assume equality for cyclic structures. The algorithm for detecting cyclic
        // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
        var length = stack.length;
        while (length--) {
            // Linear search. Performance is inversely proportional to the number of
            // unique nested structures.
            if (stack[length] == a) return true;
        }
        // Add the first object to the stack of traversed objects.
        stack.push(a);
        var size = 0, result = true;
        // Recursively compare objects and arrays.
        if (className == '[object Array]') {
            // Compare array lengths to determine if a deep comparison is necessary.
            size = a.length;
            result = size == b.length;
            if (result) {
                // Deep compare the contents, ignoring non-numeric properties.
                while (size--) {
                    // Ensure commutative equality for sparse arrays.
                    if (!(result = size in a == size in b && this.isEqual(a[size], b[size], stack))) break;
                }
            }
        } else {
            // Objects with different constructors are not equivalent.
            if (a.get('constructor').toString() != b.get('constructor').toString()) {
                return false;
            }

            // Deep compare objects.
            for (var key in a) {
                if (a.hasOwnProperty(key)) {
                    // Count the expected number of properties.
                    size++;
                    // Deep compare each member.
                    if ( !(result = b.hasOwnProperty(key) )) break;
                }
            }
        }
        // Remove the first object from the stack of traversed objects.
        stack.pop();
        return result;
    }
});

这篇关于如何*不*在Ember.js中退出路由时销毁View的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆