KnockOutJS - 单个视图中的多个ViewModel

CLi*_*own 200 data-binding mvvm knockout-mapping-plugin knockout.js

我认为我的应用程序现在变得非常大,太大而无法使用单个ViewModel处理每个View.

所以我想知道创建多个ViewModel并将它们全部加载到一个View中会有多困难.需要注意的是,我还需要能够将X ViewModel数据传递到Y ViewModel数据中,以便各个ViewModel需要能够相互通信或至少相互了解.

例如,我有一个<select>下拉列表,选择下拉列表具有一个选定的状态,允许我在<select>另一个ViewModel 中将所选项目的ID传递给另一个Ajax调用....

在单个视图中处理众多ViewModel的任何要点赞赏:)

san*_*ppa 284

Knockout现在支持多个模型绑定.该ko.applyBindings()方法采用可选参数 - 要激活绑定的元素及其后代.

例如:

ko.applyBindings(myViewModel, document.getElementById('someElementId'))
Run Code Online (Sandbox Code Playgroud)

这会将激活限制为具有ID someElementId及其后代的元素.

有关详细信息,请参阅文档

  • 如果你想使用jQuery选择器,你需要添加`[0]`来指定一个实际的DOM元素(而不是jQuery对象),如下所示:`ko.applyBindings(myViewModel,$('#someElementId') [0])` (72认同)
  • 这应该是公认的答案.您仍然可以使用当前接受的答案所具有的主对象,然后将各个视图模型绑定到页面上的相应元素.这将节省性能,并限制数据绑定所需的范围. (3认同)

Joh*_*apa 149

如果它们都需要位于同一页面上,一种简单的方法是使主视图模型包含其他视图模型的数组(或属性列表).

masterVM = {
    vmA : new VmA(),
    vmB : new VmB(),
    vmC : new VmC(),
}
Run Code Online (Sandbox Code Playgroud)

然后,masterVM如果需要,您可以为页面本身提供其他属性.在这种情况下,视图模型之间的通信并不困难,因为您可以通过它进行中继masterVM,或者您可以使用$parent/ $rootin绑定或其他一些自定义选项.

  • @CLiown你可以使用`with:`bindging,所以你不会重复自己 (12认同)
  • @CLiown是的,如果你绑定到masterVM,你可以这样做.您可以使用"with"绑定来帮助避免在您深入了解子视图模型时的点语法. (4认同)
  • 所以我能够做类似的事情:data-bind ="text:masterVM.vmA",我想我仍然可以使用附加了DOM元素的ko.applyBindings.假设这也意味着我可以这样做:data-bind ="$ parent.masterVm"? (2认同)

Jan*_*ana 21

这是我在单视图中完成包含大量ViewModel的大型项目后的答案.

Html视图

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <div id="container1">
        <ul>
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <div id="container2">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <script src="js/jquery-1.11.1.js"></script>
    <script src="js/knockout-3.0.0.js"></script>
    <script src="js/DataFunction.js"></script>
    <script src="js/Container1ViewModel.js"></script>
    <script src="js/Container2ViewModel.js"></script>

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

对于这个视图,我在两个单独的javascript文件中为id = container1和id = container2创建了2个视图模型.

Container1ViewModel.js

function Container1ViewModel()
{
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");

} 
Run Code Online (Sandbox Code Playgroud)

Container2ViewModel.js

function Container2ViewModel() {
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("XYZ");
    self.myItems.push("PQR");

}
Run Code Online (Sandbox Code Playgroud)

然后在这两个视图模型在DataFunction.js中注册为单独的视图模型之后

var container1VM;
var container2VM;

$(document).ready(function() {

    if ($.isEmptyObject(container1VM)) {
        container1VM = new Container1ViewModel();
        ko.applyBindings(container1VM, document.getElementById("container1"));
    }

    if ($.isEmptyObject(container2VM)) {
        container2VM = new Container2ViewModel();
        ko.applyBindings(container2VM, document.getElementById("container2"));
    }
});
Run Code Online (Sandbox Code Playgroud)

像这样你可以为不同的div添加任意数量的viewmodel.但请确保不要为已注册的div内的div创建单独的视图模型.