3

私がCollectionViewember.jsにいるとしましょう。

最初に、contentプロパティがいくつかの要素を持つ配列にバインドされているとしましょう。CollectionViewはこれらの要素をレンダリングし、それらがDOMにdidInsertElement入ると、最初に各childViewに対して呼び出され、最後にCollectionViewそれ自体に対して呼び出されます。

変更を想定してみましょうcontent(たとえば、新しいアイテムが追加されたり、配列が完全に置き換えられたりします)。はCollectionView、新しい子を追加するか、子を完全に置き換えます。それに応じてDOMが更新されます。しかし、の必要はありませdidInsertElementCollectionView

DOMにすべての変更を加えた後、カスタムJSを実行したいと思います。didRerenderElementまたはdidUpdateElementフックのようなもの。

何を試しましたが、機能しませんか?

  1. このコードをCollectionViewに入れることはできません。これdidInsertElementは、配列が変更されてDOMが更新されるたびにコードが起動されないためです。
  2. 監視を試みましたが、実際のDOM更新が行われる前にcontent、オブザーバーは常に起動していました。
  3. 観察してみchildViewsましたが、似たようなケースです。

私のために働いた1つのあいまいな解決策はこれでした:

App.MyCollectionView = Ember.View.extend({
  childrenReady: 1, // anything, value doesn't matter

  itemViewClass: Ember.View.extend({
    didInsertElement: function () {
      this.get('parentView').notifyPropertyChange('childrenReady');
    }
  }),

  childrenGotReady: function () {
    if (this.get('childViews').everyProperty('state', 'inDOM')) {
      // run that custom JS code here (e.g. apply jQuery masonry to the elements)
    }
  }.observes('childrenReady')      

});

しかし、これはあまりにもあいまいであり、他の問題も発生しがちです。

私はこれを読みました:Emberビューの一部が再レンダリングされるときはいつでもコードを実行するにはどうすればよいですか?しかし、それはsには当てはまりませんCollectionView

私は私のアプリの多くの部分でこれに遭遇しています、そして私は本当にemberjsがこれのための標準的な方法を持っていることを期待しています。

4

2 に答える 2

4

これは、子要素の配列を監視し、それらすべてがdidInsertElementを起動したときにコールバックするオブザーバーの例です。

addOnDidInsertObserver: function(children, callback) {
    var options = {
        willChange: function() {},
        didChange: function(children, removing, adding) {
            var insertedChildren = [];
            adding.forEach(function(added) {
                var onInsertElement = function() {
                    // remove this call back now (cleanup)
                    added.off('didInsertElement', onInsertElement)
                    // capture the child
                    insertedChildren.push(added);
                    // if all of the new children are rendered, fire
                    if (insertedChildren.length == adding.length) {
                        callback(insertedChildren);
                    }
                };

                added.on('didInsertElement', onInsertElement);
            });
        }
    };

    children.addEnumerableObserver(this, options);
    return {'context':this, 'children':children, 'options':options};
}

removeOnDidInsertObserver: function(observer) {
    observer.children.removeEnumerableObserver(observer.context, observer.options);
},
于 2012-11-21T14:18:38.827 に答える
0

didInsertElementはcollectionViewでも機能するはずです。ソース。ただし、CollectionViewのchildViewsプロパティを直接操作しないでください。代わりに、コンテンツプロパティからアイテムを追加、削除、置換します。これにより、レンダリングされたHTMLに適切な変更が加えられます。また、didInsertElementを呼び出します。

于 2012-11-21T12:34:50.037 に答える