在 ios safari 上设置数据列表属性后,数据列表输入元素丢失光标

datalist input element loses cursor after datalist list attribute is set on ios safari

我有一个 html 数据列表元素,我试图仅在字段中输入两个以上字符时才显示自动完成列表。在桌面上,您可以输入从 0 到无穷大的字符,输入永远不会失去焦点,并且列表显示得很好。但是,对于移动设备(特别是 - iOS safari),当输入的字符长度达到 3 时,尽管输入仍然具有焦点,但光标会消失。用户必须再次单击输入才能继续搜索。我会提到 Safari 浏览器会向用户显示一些不相关的自动完成结果,直到达到这个长度 3 为止。这是管理我的预期行为的数据列表上的侦听器:

  // Only show auto-complete results for greater than 2 characters.
  searchNameInput.addEventListener('keyup', e => {
    const input = e.target;
    const list = input.getAttribute('data-list');
    input.value.length > 2 ? input.setAttribute('list', list) : input.removeAttribute('list');

    // Unrelated code (i think):
    if (!input.value.length)
      filtersProxy.searchName = { name: '', city: '', stateProvince: '' };
  });

这是输入 3 个字符后浏览器的样子。请注意输入字段没有光标。 datalist实际列表也还没出现

我试过在每次 keyup 事件后使用 setTimeout return 将焦点转移到元素上,但无济于事。这个让我难住了!

这可能是一个错误。我认为在 Apple 推出补丁更新之前无法修复它。

因为这个问题也出现在 MacOS Safari 上,并且 iOS 基于 MacOS(MacOS Safari 和 iOS Safari 在内部非常相似,只是用户界面不同)这可能是一个错误Safari 处理渲染文本框的方式,在 Apple 修复他们的 HTML 渲染引擎之前不会被修复。

我有一个可怕的黑客给你。

首先,创建一个假的输入字段:

const fakeInput = document.createElement('input')
fakeInput.setAttribute('type', 'text')
fakeInput.style.position = 'absolute'
fakeInput.style.opacity = 0
fakeInput.style.height = 0
fakeInput.style.fontSize = '16px'
document.body.prepend(fakeInput)
fakeInput.focus()

接下来,使用setTimeout将焦点设置到您的input,因为直接设置它是行不通的:

if(input.value.length > 2) {
    if(!input.hasAttribute('list')) {
      fakeInput.focus();
      input.setAttribute('list', list);
      setTimeout(() => input.focus(), 10);
    }
} else input.removeAttribute('list');

瞧。