0

オブジェクトがいくつかのリストの 1 つにあるアプリケーションがあります。1 つのリストの UI は、各アイテムが他のリストのいずれかにあることを示す必要があります。

私が実装したものを大幅に簡略化したバージョンは次のとおりです。

function Item(id, panel) {
    var that = this;
    this.id = id;
    this.viewModel = panel;
    this.isSelected = ko.computed(function(){
        return panel.isSelected(that);
    });
}

function Panel() {
    var that = this;

    //my two lists
    this.all = ko.observableArray();
    this.selected = ko.observableArray();

    this.isSelected = function(item){
        return _(that.selected()).find(function(thing){
            console.log("iterating");
            return thing.id == item.id;
        });
    };
}

var panel = new Panel();
ko.applyBindings(panel);

//add some things to the list
for(var i=0; i<40; i++){
    var item = new Item(i, panel)
    panel.all.push(item);
    //let's select some of them. note it's actually a different object
    if (i % 2 == 0){
        panel.selected.push(new Item(i, panel));
    }
};
​

フィドルはこちら: http://jsfiddle.net/89j52/5/

そのため、アイテムにパネルへの参照を与えるという奇妙さを超えて、パフォーマンスもひどいものです。これは、別のアイテムを選択済みリストに追加するたびに、すべてのアイテムの選択済みステータスが再計算されるためです。「繰り返し」を何回出力するかに注意してください。その理由は理解できるが、それは苦痛だ。

明らかに、追加を行うたびにすべての項目をチェックする必要はありません。たとえば、アイテムのルックアップ テーブルを隠しておき、選択したリストに何かが追加されたときに適切なテーブルを更新することができます。しかし、それを Knockout の観測可能/計算されたものと結び付けて、UI をシームレスに更新する方法がわかりません。Knockout のイディオムの中でこれにどのように取り組むべきですか?

4

1 に答える 1

1

isSelectedを通常のオブザーバブル (計算されない)に変換し、選択したリストに項目を追加するたびに直接更新するとどうなりますか?

function select(item){
    panel.selected.push(item);
    var itemInAll = _(panel.all()).find(function(thing){
        return thing.id === item.id;
    });
    itemInAll.isSelected(true);
}

あまりエレガントではありませんが、間違いなくより効率的です。Itemにもpanelへの参照を保持する必要はありません。完全なコードは次のとおりです: http://jsfiddle.net/89j52/9/

于 2012-04-04T13:51:06.013 に答える