我正在创建一个由单个输入字段组成的敲除组件,您可以在其中搜索用户。
我正在使用click
事件从列表中获取选定的用户,并且如果输入失去焦点(也就是他们单击了其他位置),我想做一些事情,例如隐藏列表。 / p>
问题是,当我单击列表中的某个元素时,会触发hasFocus
事件,并且以某种方式阻止了click
事件的触发。
我不明白为什么,因为它们是兄弟姐妹,而不是父子事件。
我已经设法通过在hasFocus
的订阅函数中添加超时来使其工作,但是我认为这不是正确的方法。
这是唯一的方法吗?有这样的超时来使代码正常工作是不好的做法,对吧?
这是一个工作的小提琴:http://jsfiddle.net/57kxyud9/
click
事件,它可以正常工作。hasFocus
事件订阅,您可能会注意到它停止保存用户的信息。hasFocus.subscribe
内启用超时,程序将再次运行。我还应该在本文中嵌入代码段吗?
即使在input_hasFocus.subscribe
处于活动状态的情况下,我也希望能够保存用户。
答案 0 :(得分:1)
添加setTimeout
本身来更改subscribe
的顺序没有错。因为rateLimit
是淘汰赛中的有效概念。但是,一个subscribe
更新另一个observable
却又触发了subscribe
等等,似乎是不必要的。因此,如果您想要从其他可观察对象派生的observable
,则可以将其设置为computed
属性,而不是从它依赖的所有可观察对象的订户那里更新它的值。
例如,
show_matchingUsers
取决于input_hasFocus
和是否产生任何selection
。 matches
完全取决于selection
因此,您可以将它们设置为computed
的可观察对象:
var vm = function() {
var self = this;
self.users = [{"username":ko.observable("Alice")},{"username":ko.observable("Bob")},{"username":ko.observable("User 3")},{"username":ko.observable("User 4")},{"username":ko.observable("User 5")}];
self.selection = ko.observable();
self.chosenUser = ko.observable();
self.input_hasFocus = ko.observable(false);
self.matches = ko.observableArray([]);
self.show_matchingUsers = ko.observable(false);
// gets computed every time "selection" cahnges
self.matches = ko.computed(function() {
let matches = [],
val = self.selection();
if (!val) {
return matches;
}
/*for each item in the array...*/
for (i = 0; i < self.users.length; i++) {
/*check if the item starts with the same letters as the text field value:*/
if (self.users[i].username().substr(0, val.length).toUpperCase() == val.toUpperCase()) {
matches.push(self.users[i]);
}
}
return matches;
})
// gets computed every time "input_hasFocus" and "selection" cahnges
self.show_matchingUsers = ko.computed(function() {
return self.input_hasFocus() && self.selection()
}).extend({ rateLimit: 200 });
self.select_thisUser = function(u) {
self.chosenUser(u);
self.selection(u.username());
};
}
ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<br/> Selected User:
<!-- ko with:chosenUser -->
<span data-bind="text:username"></span>
<!-- /ko -->
<hr style="border-color:white;background-color:white;color:white;border-style:solid;" />
<div class="autocomplete">
<input data-bind="textInput: selection, hasFocus:input_hasFocus" autocomplete="off" type="search" placeholder="Search" />
<div data-bind="visible:show_matchingUsers,foreach:matches" class="autocomplete-items">
<div data-bind="click:function(){$parent.select_thisUser(this);}">
<span data-bind="text:username"></span>
</div>
</div>
</div>
我猜想focus
事件之前会触发click
。这就是matches
被单击之前被隐藏的原因。因此,我们可以添加200秒的rateLimit
。这基本上是指示敲除操作等待200毫秒,以便click
事件在再次计算show_matchingUsers
之前完成。