我尝试将上面的 John Earles 自定义绑定(谢谢 John!)与一个也使用 valueUpdate: 'afterkeydown' 绑定的文本字段一起使用,并发现它并没有按预期工作。(我猜这是因为当需要触发其中一个绑定时,所有绑定都会再次触发,而 valueUpdate 很可能会导致在写入每个字符后触发值绑定)。
经过几次尝试后,我对这个问题进行了半修复,这对我来说似乎工作正常。基本思想是,在我们触发 hasfocus 绑定之前,我们检查相关元素是否已经具有焦点,并且我们仅在触发 hasfocus 绑定之前元素实际上没有焦点时才实际选择文本。
我已经使用 jquery 来检查焦点,但您也可以通过其他方式进行检查。
ko.bindingHandlers.hasSelectedFocus = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.bindingHandlers['hasfocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var focusBefore = $(element).is(':focus');
ko.bindingHandlers['hasfocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
var selected = ko.utils.unwrapObservable(valueAccessor());
if (selected && !focusBefore) {
element.select();
}
}
};
编辑:我注意到这种绑定在 iOS 设备上使用时可能无法完全按照您的意愿工作。这样的绑定没有任何问题,但是自动对焦和选择逻辑会导致设备键盘在绑定执行后立即出现,这可能是也可能不是您希望在此类设备上发生的事情。相比之下,在我用来测试的 android 设备上,我不会在此绑定执行后立即自动获取键盘。为了我的缘故,我最终通过以下方式创建了另一个绑定,在 iOS 设备上什么都不做。
ko.bindingHandlers.hasNonIosSelectedFocus = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
if (navigator.userAgent.match(/iPad/i) == null && navigator.platform.indexOf("iPhone") == -1 && navigator.platform.indexOf("iPod") == -1) {
ko.bindingHandlers['hasSelectedFocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
if (navigator.userAgent.match(/iPad/i) == null && navigator.platform.indexOf("iPhone") == -1 && navigator.platform.indexOf("iPod") == -1) {
ko.bindingHandlers['hasSelectedFocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
}
}
};
Tl;博士:
如果您使用它并且想要满足平板电脑/智能手机的需求,那么请务必测试这是您实际期望的交互逻辑。