【问题标题】:KnockoutJS how to make different ViewModels work toghether?Knockout JS 如何让不同的 ViewModel 协同工作?
【发布时间】:2013-12-22 16:46:27
【问题描述】:

假设我的主视图包含

  • 可预订项目
  • 购物车

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

<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'));

我有 2 个问题。

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

2) 关于 KO 或 MVVM 本身,我做错了什么吗?

Fiddle Here

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

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

    在您的情况下,我倾向于使用构图。因此,如果我有一个由功能元素组成的视图,我倾向于将这些单独的元素组成 viewModel。

    我确实发现这总体上更容易。容器 VM 可能会有一些元素实际上是单个页面的一部分。如果页面中有很多单独的视图模型,可能很难理解。另一个问题是购物车与一个容器 div 耦合。在购物车的情况下,这可能是可以接受的。在其他情况下,您的功能组件可能具有难以包含在一个 div 下的视图元素,因此很难像这样隔离视图模型。

    我已经修改了你的设计:

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

    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

    【讨论】:

    • 这似乎是一个有效的解决方案,无论如何它会导致重复的代码,因为我需要在容器 VM 中包装任何 Item/Cart 方法,我不太喜欢
    • 已在上面进行了修改以说明为什么我通常使用组合来为每个视图创建一个视图模型
    【解决方案2】:

    使用我的绑定约定库的示例,它可以轻松使用多个视图模型。 https://github.com/AndersMalmgren/Knockout.BindingConventions

    要在模型之间进行通信,您可以使用 Event Aggregate 模式,我在一个名为 SignalR.EventAggregatorProxy 的库中有一个,如果您不需要 SignalR,您可以提取 eventtaggregatorn 部分。 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-17
      • 2017-11-15
      • 2020-01-13
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多