Handlebars 表单模板,输入在使用 keyup 更新时失去焦点

Handlebars form template, input loses focus when updates using keyup

您将如何在每次数据更新时更新表单模板(把手)并保持输入元素的焦点?在我的代码示例中,您会发现一个表单字段,它附加了一个更新数据的 keyup 事件侦听器。

但是在每次更新时我都会重新呈现导致输入失去焦点的表单。

JavaScript

import "./styles.css";
import $ from "jquery";
import Handlebars from 'handlebars';

const updateHtml = data => {
  const app = $('#app');
  const html = template(data);
  app.html(html);
}

const app = $('#app');
const data = {
  foo: 'default value',
}

const template = Handlebars.compile(`<form><input type="text" id="foo" value="{{foo}}"></form>`);
updateHtml(data);

app.on('change keyup', function(e){
  const val = $(e.target).val();
  data.foo = val;
  updateHtml(data);
});

我已经创建了一个codesandbox供您测试https://codesandbox.io/s/magical-leftpad-ry2lx?file=/src/index.js

尝试输入输入,您会发现在键入后它会失去焦点。那么,如何解决这个问题,以便我可以写入输入,数据对象根据收件箱更新自身?

更新

我想提供更多关于我正在开发的实际应用程序的上下文。我创建了一个复杂的表单,其中包括复选框、单选按钮、根据另一个输入(条件字段)更改输入的中继器字段。

我不想通过事件侦听器更新 dom 元素 (adding/inserting/removing)。 Dom 应该在数据更新时更新。这就是我使用 handlebars 模板系统的原因。

我不确定这是否是您想要实现的目标的最佳实现。由于表格的复杂性已被排除在示例之外,因此很难正确评估此解决方案并提出替代方案。

此实现的问题在于您要删除表单元素并在每个 changekeyup 事件上创建一个新元素。这成为您关于输入失去焦点的问题的核心。输入是不是失去焦点;正在删除输入并用新元素替换。新输入元素获得焦点的唯一方法是您直接通过代码添加它。

当您使用 jQuery 并为您的输入元素指定 ID“foo”时,您可以使用以下方法为其分配焦点:

$("#foo").focus();

但是,将焦点设置到一个元素会将光标置于输入文本的开头,这对您的用户来说是痛苦的,因为标准行为是光标保留在文本的末尾;允许用户在不先移动光标的情况下继续输入。

也可以通过代码设置光标位置。这是一个 link 到问题已经被问过和回答过的地方:Use JavaScript to place cursor at end of text in text input element

设置焦点 设置光标的 jQuery 代码为:

$("#foo").focus().get(0).setSelectionRange(-1, -1);

我有 forked 你的 codesandbox 并添加了这一行。

此代码可能适用于您提供的简化示例,但我担心它无法扩展。

例如,如果您的表单只包含第二个文本输入,则您需要跟踪哪个输入被更改,以便将焦点和光标设置在正确的输入,而不是将焦点转移到另一个。

我认为更好的解决方案是 show/hide 表单的依赖部分与更改事件相关,而不是 替换 整个表单的每个更改和 keyup 事件。