首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Ember.js中退出路由时如何*不*销毁View

在Ember.js中退出路由时如何*不*销毁View
EN

Stack Overflow用户
提问于 2012-06-18 12:57:17
回答 2查看 3.4K关注 0票数 13

关于新的Ember.js路由系统(描述这里),如果我正确理解,视图将在退出路由时被销毁。

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

更新:看起来,视图不会被破坏,除非出口视图在新路由中被替换。例如,如果您在stateA中,在某些{出口主}中使用ViewA,而在{出口主}中使用ViewB到stateB,则ViewB将替换ViewA。解决这一问题的一种方法是在需要保留视图时定义多个出口,例如{出口master1}、{出口master2}}、.

一个很好的特性是能够将一系列的视图传递给出口。也可以选择在离开一条路线时,视图是会被破坏还是会被隐藏。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-17 07:42:21

我已经想出了如何修改路由系统,这样插入到插座中的视图就不会被销毁。首先,我重写了outlet助手,以便它将一个Ember.OutletView加载到{{outlet}}中。

代码语言:javascript
运行
复制
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按以下方式扩展了Ember.ContainerView

代码语言:javascript
运行
复制
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.isEqualisEqual的一个修改版本。

代码语言:javascript
运行
复制
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;
    }
});
票数 9
EN

Stack Overflow用户

发布于 2012-06-18 17:07:17

这样,当用户重新进入路由时,视图的状态将保持不变。

相反,我会将该信息存储在控制器(或状态管理器)中,以便在重新输入路由时,使用旧状态初始化新视图。这有意义吗?因此,例如,如果它是一个帖子列表,并且其中一个被选中,您将在控制器(或状态管理器)中存储有关选择哪个帖子的数据。在访问某一特定职位之后,然后再回到列表中,将选择相同的职位。

我可以想象一个用例,它不会很有用(例如,滚动到长长的列表中的一个特定位置),所以这可能无法回答您的问题。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11083392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档