【问题标题】:Knockout Computed Observable Only Recognizes One ObservableKnockout Computed Observable 只识别一个 Observable
【发布时间】:2018-05-26 19:15:40
【问题描述】:

背景:我正在使用 Knockout 3.4.0 制作网页。在页面上,我使用计算出的 observable 来计算费用成本(以美元为单位)。费用可以是百分比或统一费率,并且此百分比/统一费率信息可以插入两个文本框之一。我使用单选按钮和 jQuery 让用户选择哪个文本框处于活动状态,因为用户只能选择百分比统一费率。我也在使用 JSON 和 ko.mapping 加载视图模型,但这似乎不是这里的问题。还要提一下客户端的目标浏览器是IE11或者Edge。

问题: 计算出的 observable 似乎没有订阅统一费率文本框中的更改。当我在本地主机上运行应用程序时(应用程序本身是 .NET MVC),统一费率文本框响应一次。当我将代码移至JSFiddle 以撰写本文时,该框根本没有响应。这是可观察的:

self.serviceFeeComputed= ko.computed(function () {
    if (self.ServiceFee.Percentage() !== null 
        && self.ServiceFee.Percentage() !== 0) {
            return self.Amount() * (self.ServiceFee.Percentage() / 100);
    } else {
        return self.ServiceFee.FlatRate();
    }
});

解决问题的尝试:在过去的两周里,我花了大约 6 到 8 个小时试图解决这个问题。以下是我尝试过的一些事情:

  1. 我以不同的方式定义了视图模型,例如函数或 JavaScript 对象:var viewModel = { ... }

  2. 我已将 ServiceFee 转换为 observable - 没有结果,所以我改回来了。

  3. 我已将百分比文本框复制到统一费率文本框上,以确保其他属性相同。

  4. 我已从ko.computed() 切换到ko.pureComputed()

  5. 我已经切换了条件语句的运行顺序,所以我先检查self.ServiceFee.FlatRate()。这会导致统一费率文本框更新费用,而不是百分比。关闭这个事实,我进行了搜索并找到了这个SO question,但是在调用计算中的两个可观察对象时,我没有得到工作结果。我还尝试了这个解决方案的不同变体,例如使用 observables 创建变量,或者将它们加在一起。不管我做什么,条件语句中检查的第一个变量似乎是接收订阅的变量。

    self.serviceFeeComputed = ko.computed(function () {
        self.ServiceFee.Percentage();
        self.ServiceFee.FlatRate();
        if (self.ServiceFee.Percentage() !== null && self.ServiceFee.Percentage() !== 0) {
            return self.Amount() * (self.ServiceFee.Percentage() / 100);
        } else {
            return self.ServiceFee.FlatRate();
        }
    });
    

理想分辨率:无论用户在百分比和固定费率之间来回切换多少次,我都希望两个文本框都更新计算的 observable。

提前致谢。

【问题讨论】:

  • 导致the box does not respond at all 的原因是您在HTML 绑定中犯了一个拼写错误。 text: serviceFeeCompued需要固定为text: serviceFeeComputed
  • 另外,您能否从用户的角度解释您希望文本框具有什么行为?我不确定我是否理解你的目的。
  • 你用 jQuery 做的太多让你自己把事情复杂化了。您应该能够通过淘汰赛完成所需的一切,包括启用/禁用输入。
  • @trgiangvp3 - 嗨,感谢您注意到我的错字。我添加了该标签,以便我们可以在页面上看到 serviceFeeComputed。不幸的是,修复错字对原始问题没有影响。就目的而言,我希望文本框从合同总额中删除一部分。在我的示例中,我将金额初始化为 1000。如果有人在百分比框中输入“1”,则应从金额中减去 1%,并且应在“合同成本”框中显示为 990。如果有人输入“1”在统一费率框中,应从金额中减去 1,应显示为 999。
  • @Drummad - 感谢您的反馈。我将研究切换 jQuery 功能以使用 Knockout。但是,完全删除 jQuery 并启用两个文本框并不能解决此问题,您可以在此处看到:jsfiddle.net/Lof38662/8

标签: knockout.js


【解决方案1】:

您的问题来自两件事:

  1. 正如Drummad 一样 在他的评论中指出,你把事情复杂化了 错误地将 jQuery 与 KO 结合使用
  2. 您在确定何时使用 Percent 和何时使用 Flatrate 的条件方面存在错误

我已将您的代码修复为CodePen

// You will not need jQuery at all, KO is enough
// You need a boolean property to determine if the Flatrate or the Percentage is used
self.ServiceFee = {
  Percentage: ko.observable(),
  FlatRate: ko.observable(),
  IsPercentage: ko.observable(true) // Add this property to ServiceFee
};

self.serviceFeeComputed = ko.computed(function() {
  //if (self.ServiceFee.Percentage() !== null && self.ServiceFee.Percentage() !== 0) {
  if (self.ServiceFee.IsPercentage()) { // this is the right condition
    return self.Amount() * (self.ServiceFee.Percentage() / 100);
  } else {
    return self.ServiceFee.FlatRate();
  }
});
<!-- You will not need jQuery at all, KO is enough -->
<!-- You need a boolean property to determine if the Flatrate or the Percentage is used -->

<label class="radio-inline col-xs-2 col-xs-offset-1">
  <input name="Test" type="radio" data-bind="checkedValue: true, checked: ServiceFee.IsPercentage" />
  <!-- <input type="radio" name="percentageOrFlatRate" value="percentage" /> -->
</label>
... other code ...
<input class="form-control"
  data-bind="textInput: ServiceFee.Percentage, valueUpdate: 'afterkeydown', enable: ServiceFee.IsPercentage"
  data-value="percentage" id="ServiceFee_Percentage" name="ServiceFee.Percentage"
  placeholder="0.00" type="number" value="" />

... other code ...

<label class="radio-inline  col-xs-2 col-xs-offset-1">
  <input name="Test" type="radio" data-bind="checkedValue: false, checked: ServiceFee.IsPercentage" />
  <!-- <input type="radio" name="percentageOrFlatRate" value="flatRate" /> -->
</label>
... other code ...
<input class="form-control"
  data-bind="textInput: ServiceFee.FlatRate, valueUpdate: 'afterkeydown', disable: ServiceFee.IsPercentage"
  data-value="flatRate" id="ServiceFee_Percentage" name="ServiceFee.Percentage"
  placeholder="0.00" type="number" value="" />

【讨论】:

  • 感谢您的回答 - 我能够将其中的大部分内容集成到我的解决方案中,并对其进行修改以用于添加新数据和编辑预先存在的数据。我仍然有兴趣了解根本原因,以便更好地了解 KO 的机制。对于计算的 observable,KO 是否只订阅函数中的第一个 observable?
  • 不,我不这么认为。正如您在我上面发布的 CodePen 中看到的,在 serviceFeeComputed 函数中,有 3 个可观察变量,您可以从 UI 更改它们并且它们运行良好。但是,我不太了解 KO,无法解释为什么在 Flatrate 更改时不调用您的计算函数。
  • 问题完全出在你计算的逻辑上。你有self.ServiceFee.Percentage() !== null &amp;&amp; self.ServiceFee.Percentage() !== 0Percentage 永远不会是这些值中的任何一个,因为输入值是字符串,而不是数字。您可以将其更改为 self.ServiceFee.Percentage() !== null &amp;&amp; self.ServiceFee.Percentage() != 0!==!=)以匹配字符串值,但 @trgiangvp3 的解决方案可能更好。
  • 如果您将百分比值更改为0,您将看到更新统一费率值将更新计算的值。但如果百分比值非零,则计算仅使用该值而不读取统一费率值。
猜你喜欢
  • 2017-06-04
  • 1970-01-01
  • 2016-08-21
  • 2017-06-21
  • 2021-07-15
  • 1970-01-01
  • 2017-12-13
  • 2017-03-01
  • 2012-07-15
相关资源
最近更新 更多