14

親子ビュー モデル オブジェクト構造が設定されており、親のオブザーバブルを子から更新する必要があります。私は基本的にそうするための2つのパターンを考え出しました:

1] 親プロパティの参照を子に渡し、子内からプロパティを更新します。

var ParentViewModel = function(){
    var self = this;
    this.selectedItem = ko.observable();
    this.child = ko.observable(new ChildViewModel(self.selectedItem));
}

var ChildViewModel = function(parentSelectedItem){
    var self = this;
    this.id = ko.observable();
    this.parentSelectedItem = parentSelectedItem;
    this.select = function(){
        self.parentSelectedItem(self);
    }
}

2] 親で子の select メソッドを作成し、親のオブザーバブルをローカルで参照します。

var ParentViewModel = function(){
    var self = this;
    this.selectedItem = ko.observable();

    var child = new ChildViewModel();
    child.select = function(){
        self.selectedItem(child);
    }
    this.child = ko.observable(child);
}

var ChildViewModel = function(){
    this.id = ko.observable();
}

これらのパターンはどちらも私を真っ逆さまに送りません。1 つ目はプロパティ参照全体を子ビュー モデルにプッシュし、2 つ目は子のスコープ外で子の関数を定義します。

この操作をJavaScriptでクリーンでテスト可能な方法で実現する方法について、他のパターンの提案はありますか? それとも、多かれ少なかれこれら 2 つのオプションだけで行き詰っていますか?

4

1 に答える 1

20

Knockoutでこれを行う最も一般的なパターンは、子を取り込む親に「selectChild」メソッドを配置することです。ほとんどの場合、実際の子供はそれが選択されていることを知る必要はありません。

$root.selectChild次に、バインディングで、またはにバインドできます$parent.selectChild。クリック/イベントバインディングにバインドされたハンドラーに渡される最初の引数は(KO 2.0の)実際のデータであるため、メソッドは親に存在し、最初の引数として子を受け取ることができます。

var Item = function(id, name) {
    this.id = id;
    this.name = ko.observable(name);    
};

var ViewModel = function() {
    var self = this;
    this.items = ko.observableArray([
        new Item(1, "one"),
        new Item(2, "two"),
        new Item(3, "three")
    ]);  

    this.selectedItem = ko.observable();

    this.selectItem = function(item) {
        self.selectedItem(item);
    };     
};

この場合、バインディングは次のようになります。

<ul data-bind="foreach: items">
    <li>
        <a href="#" data-bind="text: name, click: $root.selectItem"></a>
    </li>
</ul>

これはjsFiddleにあります:http://jsfiddle.net/rniemeyer/anRsA/

さらに単純化することもできます。オブザーバブルは関数であり、それらに渡す最初の引数を使用して値を設定するため、selectItemメソッドを含めずに直接バインドすることもできます( http://jsfiddle.net/rniemeyer/anRsA$root.selectedItemのようになります)。/ 1 /)。私は通常、別のメソッドを明示的に使用して、適切な名前(アクション)を付けます。また、アイテムを設定する前または後に実行する必要がある追加の処理がある場合に備えて。

KO 2.0より前($rootおよびは、データを最初の引数およびハンドラー$parentとして渡すための変更とともに導入されました)、私はあなたがかなり提案した最初の方法を使用していました。そこでできることの1つは、実際には子プロパティ()を作成せず、メソッドで直接参照(引数として渡された)だけです。これは、作成されたクロージャーのために関数で使用できるためです。clickeventthis.parentSelectedItemparentSelectedItemselect

于 2012-04-04T06:00:54.693 に答える