Javascript 如何让 Knockout JS 在按键上进行数据绑定而不是失去焦点?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4386311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get Knockout JS to data-bind on keypress instead of lost-focus?
提问by Edward Tanguay
This example of knockout jsworks so when you edit a field and press TAB, the viewmodel data and hence the text below the fields is updated.
这个淘汰赛 js示例有效,因此当您编辑字段并按 TAB 时,视图模型数据以及字段下方的文本都会更新。
How can I change this code so that the viewmodel data is updated every keypress?
如何更改此代码以便每次按键都更新视图模型数据?
<!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>
回答by Sergei Golos
<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>
From the documentation
从文档
Additional parameters
valueUpdate
If your binding also includes a parameter called valueUpdate, this defines which browser event KO should use to detect changes. The following string values are the most commonly useful choices:
"change" (default) - updates your view model when the user moves the focus to a different control, or in the case of elements, immediately after any change
"keyup" - updates your view model when the user releases a key
"keypress" - updates your view model when the user has typed a key. Unlike keyup, this updates repeatedly while the user holds a key down
- "afterkeydown" - updates your view model as soon as the user begins typing a character. This works by catching the browser's keydown event and handling the event asynchronously.
Of these options, "afterkeydown" is the best choice if you want to keep your view model updated in real-time.
附加参数
值更新
如果您的绑定还包含一个名为 valueUpdate 的参数,这将定义 KO 应使用哪个浏览器事件来检测更改。以下字符串值是最常用的选项:
“更改”(默认) - 当用户将焦点移动到不同的控件时更新您的视图模型,或者在元素的情况下,在任何更改后立即更新
"keyup" - 当用户释放一个键时更新你的视图模型
"keypress" - 当用户输入一个键时更新你的视图模型。与 keyup 不同,这会在用户按住某个键时重复更新
- “afterkeydown” - 用户开始输入字符后立即更新您的视图模型。这是通过捕获浏览器的 keydown 事件并异步处理该事件来实现的。
在这些选项中,如果你想保持你的视图模型实时更新,“afterkeydown”是最好的选择。
回答by Salvador Dali
In version 3.2you can simply use textinput binding.:
在3.2 版中,您可以简单地使用textinput 绑定。:
<input data-bind="textInput: userName" />
It does two important things:
它做了两件重要的事情:
- make immediate updates
- handles browser differences for cut, drag, autocomplete ...
- 立即更新
- 处理浏览器在剪切、拖动、自动完成等方面的差异...
So no need for additional modules, custom controls and other things.
所以不需要额外的模块、自定义控件和其他东西。
回答by Jeff Mercado
If you want it to do updates on afterkeydown
"by default," you could inject the valueUpdate
binding in the value
binding handler. Just supply a new allBindingsAccessor
for the handler to use that includes afterkeydown
.
如果您希望它在afterkeydown
“默认情况下”进行更新,您可以valueUpdate
在value
绑定处理程序中注入绑定。只需提供一个 newallBindingsAccessor
供处理程序使用,包括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
};
} ());
If you're not comfortable "overriding" the value
binding, you could give the overriding custom binding a different name and use that binding handler.
如果您不习惯“覆盖”value
绑定,则可以为覆盖自定义绑定指定不同的名称并使用该绑定处理程序。
ko.bindingHandlers.realtimeValue = { 'init':..., 'update':... };
A solution like this would be suitable for Knockout version 2.x. The Knockout team has fleshed out a more complete binding for text-like inputs through the textInputbinding in Knockout version 3 and up. It was designed to handle all text input methods for text inputs and textarea
. It will even handle real time updating which effectively renders this approach obsolete.
这样的解决方案适用于 Knockout 2.x 版。Knockout 团队通过Knockout 版本 3 及更高版本中的textInput绑定为类似文本的输入充实了一个更完整的绑定。它旨在处理文本输入和textarea
. 它甚至可以处理实时更新,这有效地使这种方法过时了。
回答by RockResolve
Jeff Mercado's answer is fantastic, but unfortunately broken with Knockout 3.
Jeff Mercado 的回答很棒,但不幸的是被淘汰赛 3 打破了。
But I found the answer suggested by the ko devs while working through Knockout 3 changes. See the bottom comments at https://github.com/knockout/knockout/pull/932. Their code:
但是我在完成 Knockout 3 更改时找到了 ko 开发人员建议的答案。请参阅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/
http://jsfiddle.net/mbest/GKJnt/
EditKo 3.2.0 now has a more complete solution with the new "textInput" binding. See SalvidorDali's answer
EditKo 3.2.0 现在有了一个更完整的解决方案,带有新的“textInput”绑定。见 SalvidorDali 的回答