13

新しいEmber.jsルーティングシステム(ここで説明)に関して、私が正しく理解していれば、ルートを終了するとビューが破棄されます。

ルートを出るときにビューの破壊を回避して、ユーザーがルートに再び入るときにビューの状態が保持されるようにする方法はありますか?


更新:新しいルートでアウトレットビューが置き換えられない限り、ビューは破棄されないようです。たとえば、{{outlet master}}でViewAを使用してstateAにいて、{{outlet master}}でViewBを使用してstateBに移動した場合、ViewBがViewAを置き換えます。これを回避する方法は、ビューを保持する必要がある場合に複数のアウトレットを定義することです。たとえば、{{outlet master1}}、{{outlet master2}}、...

優れた機能は、一連のビューをアウトレットに渡す機能です。また、ルートを出るときに、ビューを破棄するか、単に非表示にするかを選択することもできます。

4

2 に答える 2

9

それ以来、アウトレットに挿入されたビューが破棄されないように、ルーティング システムを変更する方法を見つけました。まず、Handlebarsoutletヘルパーをオーバーライドして、次のようにロードしEmber.OutletViewます{{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拡張Ember.ContainerViewされます。

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()してすべてを非表示にします。次に、がすでに内部にあるかどうかを確認し、それに応じて動作します。これはUnderscoreの修正版です:childViewscurrentView_currentViewDidChange()currentViewchildViewsEmber.View.isEqualisEqual

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;
    }
});
于 2012-07-17T07:42:21.453 に答える
4

ユーザーがルートを再入力したときにビューの状態が保持されるようにします。

代わりに、その情報をコントローラー (または状態マネージャー) に保存して、ルートが再入力されたときに新しいビューが古い状態で初期化されるようにします。それは理にかなっていますか?したがって、たとえば、投稿のリストで 1 つが選択されている場合、どの投稿が選択されたかに関するデータをコントローラー (または状態マネージャー) に保存します。特定の投稿にアクセスしてからリストに戻った後、その同じ投稿が選択されます。

これがあまり役に立たないユースケース(長いリストの特定の位置にスクロールするなど)を想像できるので、それはあなたの質問に答えないかもしれません.

于 2012-06-18T17:07:17.640 に答える