javascript - 接受 KO 数字扩展中的小数位
问题描述
我已经实现了 Knockout live 1 示例中显示的扩展器 - https://knockoutjs.com/documentation/extenders.html
ko.extenders.precision = function (target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko
.pureComputed({
read: target, //always return the original observables value
write: function (newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : +newValue,
valueToWrite =
Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
},
})
.extend({ notify: "always" });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
视图模型如下:
model.gwaioDifficultySettings = {
minionMod: ko.observable(0).extend({
precision: 3,
rateLimit: { timeout: 500, method: "notifyWhenChangesStop" },
}),
};
它可以通过 HTML 输入字段访问:
<div>
<input
type="number"
style="width: 50px; padding-bottom: 0px;"
data-bind="textInput: model.gwaioDifficultySettings.minionMod"
/>
<span style="margin-left: 6px;"></span>
<loc>Minion Modifier</loc>
<span
class="info_tip"
data-bind="tooltip: '!LOC:Mandatory Minions + Star Distance * Minion Modifier = number of additional enemy Commanders.'"
>?</span
>
</div>
但是,我必须添加rateLimit: { timeout: 500, method: "notifyWhenChangesStop" }
,否则我发现一旦值为整数,该字段将删除小数点,然后它将阻止任何尝试再次输入小数点。
在实际示例中似乎并非如此,我想知道我哪里出错了,或者仅仅是因为我使用 Knockout 3 和 Chromium 28 的环境。
解决方案
我将https://gist.github.com/gnab/7579584中的一些代码添加到我的扩展器中:
if (_.isString(newValue)) {
newValue = newValue.replace(",", ".");
newValue = parseFloat(newValue);
if (!isNaN(newValue)) {
target(newValue);
}
}
这导致:
ko.extenders.precision = function (target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko
.pureComputed({
read: target, //always return the original observables value
write: function (newValue) {
if (_.isString(newValue)) {
newValue = newValue.replace(",", ".");
newValue = parseFloat(newValue);
if (!isNaN(newValue)) {
target(newValue);
}
}
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : +newValue,
valueToWrite =
Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
},
})
.extend({ notify: "always" });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
到目前为止,在我所有的测试中,这似乎都按要求执行。如果输入一个小数点,它会留下一个可见的悬挂小数点,但这似乎不会产生任何负面影响。
推荐阅读
- python - 使用 issubclass 测试类型返回不一致的结果
- database - 我们能看到在 DB2 中创建的所有临时表吗
- json - CFT 模板错误:Fn::If 中未解决的条件依赖 UseDBSnapshot
- r - 使用 R 创建 Ranger 模型以用于 MLflow 时出现问题
- mysql - PopSQL 错误:无法通过套接字 '/run/mysqld/mysqld.sock' 连接到本地 MySQL 服务器(2)
- python - 打印函数可以忽略函数返回的结果吗?
- javascript - 想要更新 React Bootstrap Tabs 的唯一子属性,但它正在重新渲染地图
- docker - Django 中的 Azure Blob 存储错误 - 无法建立新连接:[Errno 111]
- random-forest - 需要帮助让方法 = cforest 在插入符的 train() 中工作,使用留一出交叉验证
- list - 如何在 F# 中打印记录中的类型总和?