[javascript] 잃어버린 초점 대신 키 누르기를 사용하여 녹아웃 JS를 데이터 바인딩 할 수 있습니까?

녹아웃 js 예제는 필드를 편집하고 Tab 키를 누르면 뷰 모델 데이터와 필드 아래의 텍스트가 업데이트되므로 작동합니다.

키를 누를 때마다 뷰 모델 데이터가 업데이트되도록이 코드를 어떻게 변경합니까?

대체 텍스트

<!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>



답변

<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

    바인딩에 valueUpdate라는 매개 변수도 포함되어 있으면 변경을 감지하기 위해 KO를 사용해야하는 브라우저 이벤트가 정의됩니다. 다음 문자열 값이 가장 일반적으로 유용한 선택입니다.

    • “change”(기본값)-사용자가 변경 후 즉시 다른 컨트롤 또는 요소의 경우 포커스를 이동하면 뷰 모델이 업데이트됩니다.

    • “키업”-사용자가 키를 놓을 때 뷰 모델을 업데이트합니다

    • “keypress”-사용자가 키를 입력하면 뷰 모델이 업데이트됩니다. 키 업과 달리이 키는 사용자가 키를 누른 상태에서 반복적으로 업데이트됩니다.

    • “afterkeydown”-사용자가 문자 입력을 시작하자마자 뷰 모델을 업데이트합니다. 이것은 브라우저의 키 다운 이벤트를 포착하고 이벤트를 비동기 적으로 처리하여 작동합니다.

이러한 옵션 중에서 뷰 모델을 실시간으로 업데이트하려면 “afterkeydown”이 최선의 선택입니다.


답변

버전 3.2 에서는 단순히 텍스트 입력 바인딩을 사용할 수 있습니다 . :

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

두 가지 중요한 일을합니다.

  • 즉시 업데이트
  • 잘라 내기, 끌기, 자동 완성에 대한 브라우저 차이점을 처리합니다 …

따라서 추가 모듈, 사용자 정의 컨트롤 및 기타 사항이 필요하지 않습니다.


답변

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':... };

데모

이와 같은 솔루션은 Knockout 버전 2.x에 적합합니다. Knockout 팀은 Knockout 버전 3 이상의 textInput 바인딩을 통해 텍스트와 유사한 입력에 대한보다 완벽한 바인딩을 구현 했습니다. 텍스트 입력 및에 대한 모든 텍스트 입력 방법을 처리하도록 설계되었습니다 textarea. 실시간 업데이트도 처리하여이 접근 방식을 효과적으로 폐기합니다.


답변

Jeff Mercado의 답변은 환상적이지만 불행히도 Knockout 3에서 깨졌습니다.

그러나 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/

Edit
Ko 3.2.0은 이제 새로운 “textInput”바인딩을 통해보다 완벽한 솔루션을 제공합니다. SalvidorDali의 답변보기


답변