Knockout JS如何让不同的View Models协同工作?

时间:2013-12-22 16:46:28

标签: javascript knockout.js

假设我有一个包含

的主视图
  • 可预订的项目
  • 购物车

两个元素都在同一个页面中,每个元素都有自己的VM,如下所示:

<div id='page'>
    <div id='item'>
        <span data-bind='text: item().name'></span>
        <span data-bind='text: item().price'></span> EUR

        <!-- What to bind on this click handler? -->
        <button>Add</button>
    </div>

    <hr>

    <div id='cart'>
        You have 0 items in your cart.
    </div>
</div>

的Javascript

function ItemVM() {
    var self = this;
    self.item = ko.observable({id: 1, name:'test', price: 3.99});
}

function CartVM() {
    var self = this;

    // Adds an item to cart.
    self.add = function(item) {
        // Business logic here
    }

    // And so on, other methods here.
    self.remove = function(item) {}
    self.checkout = function() {}
}

ko.applyBindings(new ItemVM(), document.getElementById('item'));
ko.applyBindings(new CartVM(), document.getElementById('cart'));

我有两个问题。

1)如何在“项目”上下文中使用在其他地方定义的点击处理程序?换句话说,如何使按钮使用CartVM.add()作为点击处理程序?

2)我在参考KO或MVVM本身时有什么问题吗?

Fiddle Here

2 个答案:

答案 0 :(得分:1)

MVVM模式的想法是将视图绑定到单个viewModel。然后,您将拥有模型中描述的数据对象。

在你的情绪中,我倾向于喜欢构图。因此,如果我有一个由功能元素组成的视图,我倾向于组成这些单独元素的viewModel。

我觉得这总体来说更容易。容器VM可能会有一些实际上是单个页面的元素。如果有很多单独的viewModel是页面的一部分,那么可能很难理解。另一个问题是购物车与一个集装箱div相连。在购物车的情况下,这可能是可以接受的。在其他情况下,您的功能组件可能具有可能难以包含在一个div下的视图元素,因此很难像这样隔离viewModels。

我修改了你的设计:

注意我添加了一个要在itemVM中添加的调用,如图所示。

function ItemVM() {

    this.add = function(data, e) {
        viewModel.CartVM.add(data);
    };
}

function VM() {
     this.ItemVM = new ItemVM();
     this.CartVM = new CartVM();
}

var viewModel = new VM();
ko.applyBinding(viewModel);

在这里说明这一点:http://jsfiddle.net/q8uWW/4/

HTH

答案 1 :(得分:0)

使用我的绑定约定库的示例,它使得使用多个视图模型变得容易。 https://github.com/AndersMalmgren/Knockout.BindingConventions

要在模型之间进行通信,您可以使用Event Aggregate模式,我在一个名为SignalR.EventAggregatorProxy的库中有一个,如果您没有使用SignalR,则可以提取eventaggregatorn部分。 https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/

我的约定库的想法是为每个视图模型使用模板绑定。像

<div id='page'>
    <div id='item' data-name="item"></div>

    <hr>

    <div id='cart' data-name="cart"></div>
</div>

<script id="ItemView" type="text/html">
    <span data-name='name'></span>
    <span data-name='price'></span> EUR

    <button data-name="add">Add</button>
</script>

<script id="CartView" type="text/html">
    You have <span data-name="count"></span> items in your cart.
</script>

小提琴 http://jsfiddle.net/hL5rY/