【问题标题】:Replace an input DOM node while keeping focus在保持焦点的同时替换输入 DOM 节点
【发布时间】:2018-07-01 15:40:04
【问题描述】:

我有一个普通的 HTML 输入框:<input id=​"ip">

而且这个输入框有焦点。我通过看屏幕就知道这一点,document.activeElement 告诉我这一点。

现在我想替换这个输入节点。我这样做是:var the_new_node = document.createElement("input"); the_new_node.id="ip"; the_input_node.replaceWith(the_new_node);

但是,当我这样做时,输入框失去焦点。 document.activeElement 现在指向正文。有没有办法防止这种情况发生?

编辑:我意识到我可以打电话给.focus()。然而,在我的代码中,我不一定知道要替换的节点是否包含input

例如,在各种“虚拟 dom”实现中,它们在保留焦点的同时替换 dom 树的片段。他们是怎么做到的?

【问题讨论】:

  • 替换后为什么不用the_new_node.focus()
  • 在添加新元素后调用focus() 应该可以解决问题。尽管用完全相同的输入替换输入有什么用……
  • 代码相同,poc代码。请查看编辑。
  • “他们是怎么做到的”我敢肯定其中至少有一个是开源的,代码可供阅读......
  • Focus 作用于任何能够接收焦点的元素,因此成为activeElement 的目标。所以如果你想让document.activeElement指向新元素,调用focus()

标签: javascript html dom


【解决方案1】:

如果您只想在要替换的元素内部有焦点元素时关注新输入,您可以使用 .contains(document.activeElement) 准确编码:

function runReplace(idx) {
  document.querySelectorAll("input")[0].focus();
  setTimeout(() => {
    let p = document.getElementById("par").children[idx];
    let wasFocused = p.contains(document.activeElement);
    let newNode = document.createElement("input");
    newNode.type = "text";
    newNode.value = "replacement for child #" + idx;
    p.replaceWith(newNode);
    if (wasFocused)
      newNode.focus();
    
    console.log("Replaced ", p, " with an input; wasFocused=", wasFocused);
  }, 3000);
}
<div id="par">
  <p>This is a paragraph with <b>an <input type="text" id="inp" value="<input>"> inside</b></p>
  <p>This is a paragraph with no input inside</p>
</div>
<button onclick="runReplace(0)">Replace first paragraph in 3 seconds</button>
<button onclick="runReplace(1)">Replace second paragraph in 3 seconds</button>

面对用另一个任意子树替换任意 DOM 子树时,浏览器无法“保留”焦点,因此您必须手动完成。

【讨论】:

    猜你喜欢
    • 2018-11-22
    • 2010-10-13
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 2021-01-25
    • 2013-01-14
    相关资源
    最近更新 更多