Knockout值绑定输入类型的奇怪行为

时间:2016-02-21 12:37:29

标签: javascript knockout.js

我在KO foreach中有两个兄弟输入:

<input type="text" name="background_color"  data-bind="value: $data.background_color">
<input type="hidden" name="background_color"  data-bind="value: $data.background_color">

生成的DOM如下所示:

<input type="text" name="background_color" data-bind="value: $data.background_color">
<input type="hidden" name="background_color" data-bind="value: $data.background_color" value="#c9311b">

我通过jQuery的html函数获取该函数,然后在其他地方使用该HTML,但是当我在其他地方使用它时,文本输入的值未设置。

我的修复方法是使用attr绑定,而无效

data-bind="attr: {'value':$data.background_color}"

但这很痛苦。为什么仅为input[type="hidden"]设置了值?

使用KO v3.3.0。

1 个答案:

答案 0 :(得分:4)

文本输入的当前值根本没有反映在元素/属性级别的DOM中,因此innerHTML或jQuery&#39; s {{ 1}}无法看到它。

下面的解决方案,但首先让我们看一下html()的行为以及valuetype="text"的不同之处。

type="hidden"属性与value属性

value属性不是文本输入的值,它是文本输入的默认值。设置文本输入的值不会设置该属性。相比之下,隐藏输入区分&#34;默认值&#34;和一个&#34;当前值,&#34;因此设置value属性设置属性,因此您可以在生成的HTML中看到该属性。

value的这种行为与KO无关,它只是在原始DOM操作中发生:

&#13;
&#13;
value
&#13;
document.getElementById("the-text-field").value = "text field value";
document.getElementById("the-hidden-field").value = "hidden field value";
&#13;
&#13;
&#13;

这包含在HTML5规范here中,其中讨论了<input id="the-text-field" type="text" name="background_color" > <input id="the-hidden-field" type="hidden" name="background_color">属性及其具有的不同模式:

  

value IDL属性允许脚本操纵输入元素的值。该属性处于以下模式之一,用于定义其行为:

     

<强>值

     

获取时,必须返回元素的当前值。在设置时,必须将元素的值设置为新值,将元素的脏值标志设置为true,如果元素的类型属性为,则调用值清理算法当前状态定义一个,然后,如果元素具有文本输入光标位置,则应将文本输入光标位置移动到文本字段的末尾,取消选择任何选定文本并将选择方向重置为无。

     

默认

     

获取时,如果元素具有value属性,则必须返回该属性的值;否则,它必须返回空字符串。在设置时,必须将元素的value属性设置为新值。

     

... (还有其他几种模式)

...和here,其中value&#39; s input type="hidden"使用&#34;默认&#34;模式,但value使用&#34;值&#34;模式(你必须向下滚动一下&#34; IDL属性和方法&#34; table; input type="text"是列出的第三个。)

解决方案

正如您所发现的,解决方案是确保设置value属性。正如你所提到的,你可以使用value绑定来做到这一点,但是你说的有点痛苦。相反,您可以自己设置custom binding,将值设置为默认值;由于默认值在DOM中反映为attr属性,因此您会在value中看到它:

&#13;
&#13;
html()
&#13;
// The binding handler
ko.bindingHandlers.valueWithAttr = {
  update: function(element, valueAccessor) {
    element.value = element.defaultValue = ko.unwrap(valueAccessor());
    // Or we could do:
    // var value = ko.unwrap(valueAccessor());
    // element.value = value;
    // element.setAttribute("value", value);
    // ...but since that's what setting `defaultValue` does...
  }
};

// Using it
var vm = {
  background_color: "blue"
};
ko.applyBindings(vm, document.body);

$("<pre>").text(
  "html of the inputs: " +
  $("#container").html()
).appendTo(document.body);
&#13;
&#13;
&#13;