首先要做的事情。您的示例代码在 input 节点上使用 a text binding,这并不是那么有用(这意味着从视图模型到 DOM 的 单向 绑定,即“文本”内容input 没有意义)。鉴于存在valueUpdate 绑定,您可能是指the value binding?注意the textInput binding 是在现代版本的 KnockoutJS 中结合这两者的方式。
至于你的实际问题,缺少重要的背景:为什么你(认为你)想要这样做?根据具体情况,解决方案会有所不同,或者您甚至可能拥有XY-problem。
无论如何,答案。
选项 1
尽管如此,为了回答具体问题,我第二次 @JohnnyHK's answer 在您的 observable 上写一个 .subscribe 作为一种可能的解决方案。
选项 2
另一种可能的解决方案与该解决方案非常相似,但试图满足“我对输入的值不感兴趣”部分,我建议使用只读计算的 observable:
function Root() {
var self = this;
self.filter = ko.computed({
read: function() { return ""; }, // <-- not recommended, read context!
write: function(newValue) {
// You're free to discard the newValue <-- not recommended, read context!
alert("Input has been changed.");
}
});
}
ko.applyBindings(new Root());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<input data-bind="textInput: filter">
现在这会显式丢弃写入位中的newValue(根据您的要求),因此还有一个看起来很奇怪的read 函数。 我不建议这样做,而是建议使用带有支持 observable 的私有变量来进行读写。但实际上,这将使该选项等同于其他答案中的第一个选项。
一个有趣的注释,你的问题是关于“收集器”和过滤输入的:如果你看一下the docs from writeable computeds,你会发现如果它满足某个条件 是,是否接受用户输入> 实际上是一个用例。
选项 3
我会推荐什么,如果我稍微改一下您的要求:
当您的操作不关心实际的 value 时,您如何对使用惯用 KnockoutJS 的 input value 更改做出反应?
对于编写与 DOM 的自定义交互,有 custom binding handlers。您可以拥有一个根本不使用 ViewModel 的模型,也可以拥有一个具有 observable 的模型。
选项 3.A
ko.bindingHandlers["opacitor"] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
$(element).on("keydown", function() {
$(this).animate({ opacity: 0.05 }, 1000, function() { $(this).animate({ opacity: 1.0 }, 1000); });
});
}
}
ko.applyBindings({});
input { background-color: gold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<input data-bind="opacitor">
选项 3.B
或者使用视图模型的第二个选项:
ko.bindingHandlers["opacitor"] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
$(element).on("keydown", function() {
var speed = ko.utils.unwrapObservable(valueAccessor)();
$(this).animate({ opacity: 0.05 }, speed, function() { $(this).animate({ opacity: 1.0 }, speed); });
});
}
}
// speed1 and speed2 could also be observables
ko.applyBindings({ speed1: 500, speed2: 2000 });
input { background-color: gold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<input data-bind="opacitor: speed1">
<input data-bind="opacitor: speed2">
选项 3A 和 3B 的缺点是您需要编写自定义事件处理逻辑。如果您查看the textInput source from KO,您会发现跨浏览器正确处理这些事情并非易事。所以使用选项 1 或 2 可能仍然更好(即使“你不感兴趣”,你也会有一些视图模型交互)。
选项 4
使用the event binding。这具有与选项 3 相同的缺点,但仍然可能是一个简单的解决方案。这是一个例子:
function Root(){
var self = this;
self.myFn = function(data, element) {
console.log(element.target.value);
return true;
};
}
ko.applyBindings(new Root());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<input data-bind="event: { keyup: myFn }">
您将在最后一个中看到一个微妙的变化,以及一个我想结束的问题:您实际上是否没有 this issue,您实际上需要 new 值,因此不应该看afterkeydown,而是看不同的事件?