KnockoutJS дроссельной заслонки
Я пытаюсь реализовать что-то вроде безопасных типов ViewModel с использованием KnockoutJS. Он работает довольно хорошо, пока я не начну обновлять наблюдаемые через теги ввода HTML.
Я реализовал type
Экстендер, который возвращает вычисляемую наблюдаемость:
return ko.computed({
read: target,
write: fixer
})
куда fixer
это что-то вроде:
function (newValue) {
var current = target(),
valueToWrite = (newValue == null ? null : fixNumber(newValue, 0));
if (valueToWrite !== current) target(valueToWrite);
else if (newValue !== current) target.notifySubscribers(valueToWrite);
}
А также fixNumber
является
function fixNumber(value, precision) {
if (value == null || value === '') return null;
var newValue = (value || '').toString().replace(/^[^\,\.\d\-]*([\.\,\-]?\d*)([\,\.]?\d*).*$/, '$1$2').replace(/\,/, '.'),
valueToWrite = Number(newValue);
return !!(valueToWrite % 1) ? round(valueToWrite, precision) : valueToWrite;
}
Это выглядит не так просто, но я должен рассмотреть возможность использования запятой в качестве десятичного разделителя.
Часто мне нужно обновить мои наблюдаемые, как только пользователь нажмет клавишу, чтобы немедленно отразить это изменение:
<input type="text" data-bind="value: nonThrottled, valueUpdate: 'afterkeyup'"></input>
И здесь возникает много проблем, потому что, например, я не могу ввести десятичные значения меньше 1 (0,1, 0,2 и т. Д.).
Когда я пытаюсь подавить наблюдаемое, это в основном работает. Но иногда пользовательский ввод и фиксатор типов не синхронизируются, поэтому иногда кажется, что некоторые вводы теряются.
Полный пример есть http://jsfiddle.net/mailgpa/JHztW/. Я был бы очень признателен за любые советы, так как я потратил несколько дней, пытаясь решить эти проблемы.
ОБНОВЛЕНИЕ 11/04/2013
Я решил мою проблему с предоставлением пользовательских value
привязка, так что теперь наблюдаемые объекты не время от времени потребляют мой вклад.
Я добавил дополнительную привязку опции valueThrottle к обновлению throttle значения элемента:
var valueThrottle = allBindingsAccessor()["valueThrottle"];
var valueThrottleTimeoutInstance = null;
/* ... */
if (valueThrottle) {
clearTimeout(valueThrottleTimeoutInstance);
valueThrottleTimeoutInstance = setTimeout(function () {
ko.selectExtensions.writeValue( element, ko.utils.unwrapObservable(valueAccessor()) );
}, valueThrottle);
} else applyValueAction();
Также я заметил, что невозможность ввода значений, таких как 0,2, в моем случае проистекает из этого утверждения в оригинале value
связывание:
if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
valueHasChanged = true;
Я переписал это как
if ((newValue === 0) && (elementValue != 0))
valueHasChanged = true;
Это работает по крайней мере на Chrome, но я не проверял это должным образом и даже не уверен, что это правильно.
Пример должен быть добавлен, по какой-то причине jsFiddle не принимает мою пользовательскую привязку.
Любые комментарии действительно приветствуются.