【问题标题】:How to detect changes besides the change event in knockout.js如何在 knockout.js 中检测除更改事件之外的更改
【发布时间】:2012-10-19 15:03:36
【问题描述】:

我正在使用 knockout.js。我创建了一个视图模型,比如 testViewModel,只有 1 个可观察属性 testProperty

function testViewModel()
{
  var self = this;

  self.testProperty = ko.observable("Initial");

}

然后我创建了一个span,其中反映了testProperty 的更改值和一个input text field,我们可以通过它更改testProperty 值。

 <span data-bind="text: testProperty"></span><br />
 <input type="text" data-bind="value: testProperty" />

我创建了一个Example Fiddle。似乎在输入文本字段上执行focusout事件时更新了observable属性值。

现在我的问题是,我们能否将可观察属性值更新事件从 focusout 更改为其他内容。我还创建了一个保存按钮。有什么方法可以仅在按下保存按钮时更新可观察的属性值。

我正在尝试创建一个应用程序,用户可以在其中创建和保存其配置文件并可以编辑保存的配置文件。我在创建和编辑表单中使用相同的可观察属性,这些属性是可观察的。因此,当用户编辑其个人资料时,用户界面不应 更新直到用户按下保存按钮。这是我的目标。请帮我解决这个问题?

【问题讨论】:

    标签: javascript jquery knockout.js


    【解决方案1】:

    我建议有 testProperty 和 testProperty_temp。将输入绑定到 temp,单击按钮时,将 testProperty 设置为 testProperty_temp

    function testViewModel()
    {
       var self = this;
    
       self.testProperty = ko.observable("Initial");
       self.testProperty_temp = ko.obserable("");
       self.save = function() { self.testProperty(self.testProperty_temp()); }
     }
    

    希望对你有帮助

    【讨论】:

    • 感谢您的回复,但我有很多属性,所以将属性计数加倍(意味着创建每个属性的副本)是一个好习惯吗?
    【解决方案2】:

    另一种意思,与马特·伯兰德建议的思路相同:

    http://jsfiddle.net/mori57/PQxJC/

    基本上,将您的输入和按钮包装在一个表单中,并将该表单绑定到提交:这由您的 ViewModel 上的一个方法处理。看看我内联的 cmets,但这里是给那些不想出去玩 jsFiddle 的人的:

    <span data-bind="text: testProperty"></span><br />
    <!-- wrap the input and button in a form and
       data-bind to submit, with a reference
       to a handler on your viewmodel -->
    <form data-bind="submit: updateProfile">
    <!-- this must be bound to your shadow value -->
    <input type="text" data-bind="value: _tmpTestProperty" />
    <button type="submit">save</button>
    </form>​
    

    在你的 javascript 中

    function testViewModel()
    {
      var self = this;
    
      self.testProperty = ko.observable("Initial");
      // Create the "shadow" property
      // and prepopulate it with testProperty's value
      self._tmpTestProperty = ko.observable(self.testProperty());
    
      // Create our form handler
      self.updateProfile = function(val){
        // set the testProperty value to the 
        // value of the shadow property
        self.testProperty(self._tmpTestProperty());
      };
    
    }
    
    ko.applyBindings(new testViewModel());​
    

    这样,当你失去对文本输入框的关注时,你的值不会改变,而只会在你提交表单时更新。

    【讨论】:

    • 感谢您的回复,但我有很多属性,所以将属性计数加倍(意味着创建每个属性的副本)是一个好习惯吗?
    • 我会考虑,无论是使用 Knockout 还是 jQuery 还是普通的旧 Javascript,我需要积极更新多少东西,并且只更新或绑定我必须的属性> 动态更新。我不知道 Knockout 的性能开销是多少,或者字段绑定的上限是多少(如果有的话),但是在其他条件相同的情况下,请使用奥卡姆剃刀:最简单的解决方案是最好的解决方案。如果您发现自己过于复杂,可能是时候退后一步,重新评估您要解决的问题,看看是否有更简单的解决方案。
    【解决方案3】:

    您最简单的方法是为每个属性设置一个 shadow 属性。因此,您将一个绑定到您的文本框,并且仅在单击保存时将值复制到另一个属性,即绑定到其他 UI 元素的那个。

    请看这里:http://jsbin.com/aguyud/5/edit

    使用两个模型和 $.extend 从一个模型复制到另一个模型的更简单方法:

    http://jsbin.com/aguyud/7/edit

    更新,实际上从头开始,这似乎不起作用。我尝试了这个:

    http://jsbin.com/aguyud/22/edit

    第一次有效,但是在使用 $.extend 复制模型后,它似乎也复制了所有绑定,所以它只有效一次!

    【讨论】:

    • 感谢您的回复,但我有很多属性,所以将属性计数加倍(意味着创建每个属性的副本)是一个好习惯吗?
    • @TomRider:另一种方法是创建两个单独的模型。如果它们具有不同的父 DOM 元素,则可以在页面上绑定多个模型。然后,您可以将一个绑定设置为可编辑,将另一个绑定设置为显示。当您单击保存时,您只需将可编辑值复制到显示值。或者更好的是clone it。也许比每个变量都有两个副本更容易一些?
    • @TomRider:我在答案中添加了另一个版本,它消除了保留复制每个属性的复杂性,只需保留两个模型。只要您可以将每个模型绑定到不同的 DOM 元素,它就可以工作。或者,您可以将它们嵌套在单个父视图模型中以消除该限制。
    猜你喜欢
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2015-05-28
    相关资源
    最近更新 更多