【问题标题】:knockout - reusing the same view model淘汰赛 - 重用相同的视图模型
【发布时间】:2013-06-06 16:37:38
【问题描述】:

我们以购物车为例...

每次用户选择商品时,我们都会将其移至购物车的一行。

/* would normally autoincrement */ 
var num = '1'; 
document.getElementById('cart').innerHTML = oldHTML + 
"<div id='line" + num + "'>
<input type='text' data-bind='value: quantity'>
<input type='text' data-bind='value: price'>
<input type='text' data-bind='value: extendedPrice'>
</div>";`

var lineVM () {
    var self = this;
    self.quantity = ko.observable();
    self.price = ko.observable();
    self.extendedPrice = ko.computed(function () {return self.price() * self.quantity();});
}

ko.applyBindings(new lineVM(), document.getElementById('line' + num));

随着行的添加,我们有 line1、line2 等...

来自文档:

您可以选择传递第二个参数来定义要在文档的哪个部分搜索数据绑定属性。例如,ko.applyBindings(myViewModel, document.getElementById('someElementId'))。这会将激活限制为 ID 为 someElementId 的元素及其后代,如果您希望拥有多个视图模型并将每个模型与页面的不同区域相关联,这将非常有用。

测试表明没有分离......如果我重用视图模型,然后添加另一行“空白”它之前的那一行。但是,对于不确定的行数,我需要相同的视图模型。我不想为每条潜在产品线创建 100 个视图模型,也不希望我的购物车因将拥有 101 件商品的客户而损坏。

那么,如果我有一个单一的视图模型并且想要将它与页面上的多个区域相关联怎么办?文档并没有真正说。我是不是做错了,我是在尝试做 Knockout 不允许的事情吗?

非常感谢您的帮助。

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    我认为您应该从整体上重新考虑您的设计。为什么不这样做呢?

    var viewModel = function () {
        var self = this;
        self.items = ko.observableArray();
        self.addItem = function(num, quantity, price) {
            var item = {
                num: num,
                quantity: ko.observable(quantity),
                price: ko.observable(price)
            };
            item.extendedPrice = ko.computed(function() {
                return item.price() * item.quantity();
            }, self);
            self.items.push(item);
        };
    };
    
    ko.applyBindings(new viewModel());
    

    HTML:

    <div data-bind="foreach: items">
        <div data-bind="attr: { id: 'line' + num }">
            <input type="text" data-bind="value: quantity" />
            <input type="text" data-bind="value: price" />
            <input type="text" data-bind="value: extendedPrice" readonly="readonly" />
        </div>
    </div>
    

    原理是在observableArray中添加item来改变视图。你真的不应该动态地创建视图模型。

    使用此代码,您必须有某种方式调用self.addItem,这取决于您设计代码的其余部分。

    编辑:顺便说一句,你代码中的var lineVM () {应该是var lineVM = function () {

    另外,很抱歉,如果此代码中的某些人不起作用,它未经测试,但应该可以帮助您了解这个想法。

    【讨论】:

    • 如果使用淘汰赛需要我完全重新设计我的页面,那么我可以只使用标准的 javascript 处理程序。我使用了一个简单的示例,因为没有人愿意阅读 300 行代码……“真正的”应用程序使用 Google 地图,并带有它的听众。仅仅为了完成这项工作而转换 300 行代码太多了。更不用说在尝试连接两组独立的事件处理程序时,我不期待遇到下一个“我该怎么做”。不过,我非常感谢这个答案,我相信它会在不太复杂的环境中为更复杂的数据映射派上用场。
    • 是的,如果使用得当,使用淘汰赛通常需要重新设计。它旨在将视图与视图模型分开。使用淘汰赛,您根本不应该使用 javascript 更新视图 (html)。这样做会破坏淘汰赛使用的 MVVM 模式。您应该只使用 javascript 更新 observables 和 observableArrays(在视图中引用这些对象)。从长远来看,它会让事情变得更简单,我强烈建议遵循 MVVM 模式。祝你的应用好运!
    猜你喜欢
    • 1970-01-01
    • 2011-12-21
    • 2013-05-31
    • 2020-12-19
    • 1970-01-01
    • 2018-06-25
    • 2015-08-17
    • 2013-02-18
    • 2019-11-14
    相关资源
    最近更新 更多