【问题标题】:Why does JS .focus() only work inside a setTimeout of 50ms or longer为什么 JS .focus() 只能在 50ms 或更长的 setTimeout 内工作
【发布时间】:2019-05-22 15:49:09
【问题描述】:

问题

我正在为客户创建一个工作页面,其中包含一个滑出式搜索栏。当我单击一个打开搜索输入字段的按钮(它开始隐藏)时,我希望焦点(光标)移动到搜索栏(输入)。

出于某种奇怪的原因,我似乎能够获得焦点来切换输入字段的 ONLY 方法是,如果我将它放在 setTimeout 中,最短时间约为 50 毫秒(我试过 0 ,但不起作用)。

奇怪的警告 - 当我关闭搜索栏(单击隐藏搜索的打开/关闭按钮)时,我可以暂时输入字段获得焦点/光标,但当它打开时却没有,这正是我想要的。除非它在 ​​setTimeout....

我尝试过的

将焦点设置为其他内容,然后对其进行模糊处理,然后将焦点设置为我的输入字段。 [x]

  • 用 0 毫秒 [x] 将 .focus() 包装在 setTimeout

  • 将焦点设置到我创建的另一个“测试”输入字段。 [作品]

  • tabindex添加到-1 [x]的输入

const icon = document.getElementById("search-icon");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");

icon.parentElement.addEventListener("click", e => {
  form.classList.toggle("visible");
  icon.classList.toggle("fa-search");
  icon.classList.toggle("fa-times");  

  setTimeout(() => input.focus(), 50);

});
<div class="header__search">
    <i id="search-icon" class="fas fa-search">click me</i>
    <form
      id="search-form"
      class="header__search-area"
      onclick="event.stopPropagation()"
    >
      <input
        id="search-input"
        tabindex="-1"
        type="text"
        placeholder="Enter Search Term..."
      />
      <button type="submit">search</button>
    </form>
</div>

为了更快地理解,您单击图标 (id=search-icon),它会在其旁边显示一个绝对位置的表单,其中包含我想要关注的“输入”。

如果有人能解释这一点,那就太棒了。 Google 提供了否定的答案。

【问题讨论】:

  • 我已经编辑了你的问题,所以代码是可运行的,并且图标元素是可见和可点击的
  • 你的浏览器是什么?
  • 我的浏览器是 Chrome,尽管在 Firefox 和 Safari 中也发生了同样的事情。克里斯,另一个聊天阻止我添加 cmets,我还不能在 SO 上“聊天”。我正在向输入添加一个可见类,是的,它会取消隐藏它,但理论上这是在焦点之前发生的?

标签: javascript


【解决方案1】:

因为您刚刚单击了某个东西并用鼠标设置了焦点,然后您就立即更改了它。第一次聚焦(点击时)需要先完成。

如果您在mouseup 事件上执行此操作,则您单击只需立即更改焦点,而不会延迟,因为那是释放鼠标按钮的时间。见下文。


编辑

再想一想……我真的不确定了。复制了您的代码并消除了延迟,但效果很好。

const icon = document.getElementById("search-icon");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");

icon.parentElement.addEventListener("click", e => {
  form.classList.toggle("visible");
  icon.classList.toggle("fa-search");
  icon.classList.toggle("fa-times");  
  
  input.focus();

});
<div class="header__search">
    <i id="search-icon" class="fas fa-search">click me</i>
    <form
      id="search-form"
      class="header__search-area"
      onclick="event.stopPropagation()"
    >
      <input
        id="search-input"
        tabindex="-1"
        type="text"
        placeholder="Enter Search Term..."
      />
      <button type="submit">search</button>
    </form>
</div>

【讨论】:

  • 好的,这是有道理的,但有几点: - 为什么 setTimeout 为 1 的 ms 时间不起作用。 - 为什么 setTimeout 为 0 时的 ms 时间不起作用(大概这仍然会在其他所有操作完成后发生?)。
  • 是不是因为setTimeout中的回调不是和JS竞争,而是浏览器的对焦功能起作用? (对不起,我的知识不完整)。
  • 如果单击并按住鼠标按钮一会儿然后松开会发生什么?您问题中的工作代码示例会有所帮助。
  • 哈,抱歉 - 再次编辑它!您的代码没有延迟,对我来说效果很好。也许是别的东西?可能是您在表单中添加了visible 类吗?我认为这意味着它最初是隐藏的,您不能将焦点设置在隐藏元素上。
  • @AlexisWilke 我删除了过渡,并删除了 setTimeout,它正在工作!因此,大概与此有关。不过奇怪的是,如果我将转换减少到 0.125 秒,setTimeout 仍然只能在大约 15(0015 毫秒)的最小持续时间下工作。奇数...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多