如何让 Knokout JS 在按键时进行数据绑定而不是失焦?

这个 击倒 J示例的工作原理是,当您编辑字段并按 TAB 时,视图模型数据以及字段下面的文本将被更新。

如何更改此代码以便每次按键时更新视图模型数据?

alt text

<!doctype html>
<html>
<title>knockout js</title>
<head>
<script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script>
<script type="text/javascript">
window.onload= function() {


var viewModel = {
firstName : ko.observable("Jim"),
lastName : ko.observable("Smith")
};
viewModel.fullName = ko.dependentObservable(function () {
return viewModel.firstName() + " " + viewModel.lastName();
});


ko.applyBindings(viewModel);
}
</script>
</head>
<body>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
</body>
</html>
79240 次浏览
<body>
<p>First name: <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" /></p>
<p>Last name: <input data-bind="value: lastName, valueUpdate: 'afterkeydown'" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
</body>

来自 文件

附加参数

  • 更新

    如果绑定还包含一个名为 valueUpdate 的参数,则此 定义 KO 应该使用哪个浏览器事件来检测更改 下面的字符串值是最常用的选择:

    • “ change”(默认值)-当用户 将焦点移到另一个控件,或者在 元素,在任何更改后立即

    • “ keyup”-当用户释放密钥时更新视图模型

    • “ keypress”-当用户键入一个 与 keyup 不同,这会在用户持有一个密钥时反复更新 下降

    • “ after keydown”-在用户更新视图模型时立即更新 开始键入一个字符。这通过捕获浏览器的 事件并异步处理该事件。

在这些选项中,如果您愿意,“ after keydown”是最好的选择 实时更新视图模型。

如果希望它“默认”对 afterkeydown进行更新,可以将 valueUpdate绑定注入到 value绑定处理程序中。只需提供一个新的 allBindingsAccessor供处理程序使用,其中包括 afterkeydown

(function () {
var valueHandler = ko.bindingHandlers.value;
var getInjectValueUpdate = function (allBindingsAccessor) {
var AFTERKEYDOWN = 'afterkeydown';
return function () {
var allBindings = ko.utils.extend({}, allBindingsAccessor()),
valueUpdate = allBindings.valueUpdate;


if (valueUpdate === undefined) {
return ko.utils.extend(allBindings, { valueUpdate: AFTERKEYDOWN });
} else if (typeof valueUpdate === 'string' && valueUpdate !== AFTERKEYDOWN) {
return ko.utils.extend(allBindings, { valueUpdate: [valueUpdate, AFTERKEYDOWN] });
} else if (typeof valueUpdate === 'array' && ko.utils.arrayIndexOf(valueUpdate, AFTERKEYDOWN) === -1) {
valueUpdate = ko.utils.arrayPushAll([AFTERKEYDOWN], valueUpdate);
return ko.utils.extend(allBindings, {valueUpdate: valueUpdate});
}
return allBindings;
};
};
ko.bindingHandlers.value = {
// only needed for init
'init': function (element, valueAccessor, allBindingsAccessor) {
allBindingsAccessor = getInjectValueUpdate(allBindingsAccessor);
return valueHandler.init(element, valueAccessor, allBindingsAccessor);
},
'update': valueHandler.update
};
} ());

如果您不喜欢“重写”value绑定,可以给重写的自定义绑定一个不同的名称,并使用该绑定处理程序。

ko.bindingHandlers.realtimeValue = { 'init':..., 'update':... };

小样

这样的解决方案将适用于 Knokout 版本2. x。Knokout 团队已经通过 Knokout 版本3及以上的 TextInput绑定为类文本输入提供了更完整的绑定。它被设计用来处理文本输入和 textarea的所有文本输入方法。它甚至可以处理实时更新,从而有效地使这种方法过时。

Jeff Mercado 的回答非常棒,但是不幸的是3号淘汰赛被打破了。

但是我发现了 KO 开发者在处理 Knokout3更改时给出的答案。请参阅 https://github.com/knockout/knockout/pull/932的底部注释。他们的密码是:

//automatically add valueUpdate="afterkeydown" on every value binding
(function () {
var getInjectValueUpdate = function (allBindings) {
return {
has: function (bindingKey) {
return (bindingKey == 'valueUpdate') || allBindings.has(bindingKey);
},
get: function (bindingKey) {
var binding = allBindings.get(bindingKey);
if (bindingKey == 'valueUpdate') {
binding = binding ? [].concat(binding, 'afterkeydown') : 'afterkeydown';
}
return binding;
}
};
};


var valueInitHandler = ko.bindingHandlers.value.init;
ko.bindingHandlers.value.init = function (element, valueAccessor, allBindings, viewModel, bindingContext) {
return valueInitHandler(element, valueAccessor, getInjectValueUpdate(allBindings), viewModel, bindingContext);
};
}());

Http://jsfiddle.net/mbest/gkjnt/

剪辑 Ko3.2.0现在有了一个更完整的解决方案,它使用了新的“ textInput”绑定

版本3.2中,你可以简单地使用 文本输入绑定。:

<input data-bind="textInput: userName" />

它有两个重要作用:

  • 及时更新
  • 处理浏览器切割,拖动,自动完成的差异..。

所以不需要额外的模块、自定义控件和其他东西。