【问题标题】:Shared a ko.computed between two ViewModels Knockoutjs在两个 ViewModels Knockoutjs 之间共享一个 ko.computed
【发布时间】:2015-07-30 15:32:17
【问题描述】:

所以我有以下 ko.computed:

  self.grandTotal = ko.computed(function () {
        var total = self.bookBasePrice();

        if (self.TornEdge() == true)
            total += self.TornEdgeCost();

        if (self.LogoStamping() == true)
            total += self.LogoCost();

        return total;
    });

我想在两个 ViewModel 之间共享这个。我有StartViewModelUploadViewModel,我使用ko.mapping 动态创建可观察对象,这两个视图模型使用完全相同的grandTotal 计算可观察对象,尽管它们在其他方面有所不同。

有什么好的方法可以做到这一点,我查看了 ko.extenders 但这并不是我想要的。

【问题讨论】:

  • 因为我有两个视图。
  • 抱歉有点笨,视图差异很大,因此 ViewModels 计算值和 ko.validations 也有很大差异,很高兴有两个 Javascript 文件组织此代码并保持独立和整洁跨度>

标签: c# asp.net-mvc mvvm knockout.js


【解决方案1】:

这似乎是使用继承的好选择,如下所示:

function BaseVM(){
    var self = this;
    self.someValue = ko.observable();
    self.grandTotal = ko.computed(function () {
       return self.someValue()+1; 
    });
}

function Vm1(initValue){
    var self = this;
    self.someValue(initValue);
}

Vm1.prototype = new BaseVM();
Vm1.prototype.constructor=Vm1;



function Vm2(){
    var self = this;
    self.someValue(13); 
}

Vm2.prototype = new BaseVM();
Vm2.prototype.constructor=Vm2;


ko.applyBindings(new Vm1(4),document.getElementById("View1"));
ko.applyBindings(new Vm2(),document.getElementById("View2"));

在这里拉小提琴:

http://jsfiddle.net/luisvsilva/freLc1nd/3/

通常当我在 Javascript 中使用继承时,我会使用这个很棒的 sn-p 形式的 John Resig:

http://ejohn.org/blog/simple-javascript-inheritance/

【讨论】:

  • 是的,经常使用 Javascript,但是创建一个 BaseClass,我每天用 C# 做的事情在 Javascript 中却让我望而却步,我以前从未在 Javascript 中使用过继承
  • 是“Vm2.prototype.constructor=Vm1;”应该是“Vm2.prototype.constructor=Vm2;” ?
  • 是的..很好发现,更新了答案,它对你有用吗?
  • 我的错。我为 chrome 添加了 HttpsEverywhere。由于它似乎是从 CDN 加载的,因此 Knockout 正在被淘汰。
【解决方案2】:

你可以只使用一个普通的函数。所以:

self.grandTotal = myGrandTotaller;

然后定义那个函数:

function myGrandTotaller(self) {
        var total = self.bookBasePrice();

        if (self.TornEdge() == true)
            total += self.TornEdgeCost();

        if (self.LogoStamping() == true)
            total += self.LogoCost();

        return total;
    }

然后您的文本框的绑定语法将是:

data-bind="value:grandTotal($root)"

我更喜欢组合而不是继承,因为你说过它们是两个非常不同的视图/模型。因此,如果这里没有“is a”关系,我会选择“has a”,即组合。

【讨论】:

  • 嗯,我只是将另一个答案标记为正确,这里唯一的想法是,这不是 ko.computed 可观察的。如果 self.TornEdgeCost() 要更改 ko.computed 可观察对象,则 ko.computed grandTotal 会自动更新,但此解决方案不会。但我明白你关于组合优于继承的观点
  • @BrianOgden 不,它确实更新了。如果self.TornEdgeCost() 发生更改,包括grandTotal 在内的UI 将相应更新。绑定正在运行 $root 您也可以在不同的场景中使用 $data。无论哪种方式,它都与ko.computed() 一样运行...当模型值更改时,整个事情都会更新...否则重点是什么? ;-)
  • 我之前没用过$root或者记的时间太长了,谢谢你的帮助...所以$root是“父”敲除对象?
  • $parent 是父级。 $root 是主视图模型。在您的情况下,假设您没有嵌套的绑定上下文,它们可能是同一回事。在这里查看:knockoutjs.com/documentation/binding-context.html。如果您的模型发生更改,即self.TornEdgeCost() 或其他任何内容,则会触发重新绑定。而且由于您将绑定到value:grandTotal($root),它将重新计算。这是解决ko.computable 缺乏对参数的支持的一种相当标准的方法。另请注意,上述$data 也可能是另一种情况下的方式。
猜你喜欢
  • 2017-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多