在JavaScript中如何使一个变量包含潜在的无限数量的元素(或其他具有相同效果的东西)

qnzebej0  于 2023-01-04  发布在  Java
关注(0)|答案(4)|浏览(139)

我有下面的代码,它工作得很好:

window.addEventListener('load', () => {
    const values = ['input_1', 'input_2', 'input_3', 'input_4', 'input_5', 'input_6', 'input_7', 'input_8'];
    document.querySelectorAll('.box-ipt').forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box1', values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
  });

但是我需要一种方法,当我在HTML代码中添加更多的输入框时,不必回到这段代码并向变量添加更多的元素,如"input_9","input_10"等。
基本上是一种让变量接受任意数量的"input_X"元素的方法(比如"input_∞"--我知道JS中不存在∞,只是表明一个观点)。
或者可能是像for这样的循环,但它不起作用,因为在扩展重载后,输入被设置为随机输入,而不是最后一个活动输入:

window.addEventListener('load', () => {
  const inputElements = document.querySelectorAll('.box-ipt');
  const values = [];
  for (let i = 0; i < inputElements.length; i++) {
    values.push(`input_${i + 1}`);
  }
  inputElements.forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box2', values[Array.prototype.indexOf.call(inputElements, input)]));
});

我也试过这个,但它打破了扩展/浏览器:

window.addEventListener('load', () => {
  let i = 1;
  for (;;) {
    const values = [`input_${i}`];
    document.querySelectorAll('.box-ipt').forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box2', values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
    i++;
  }
});

有什么建议吗?
PS:我知道标题烂透了,如果你有更好的主意,请提出别的建议。
编辑:
更多的上下文到JS代码我有:

// Set focus after checking local storage for last focus

window.addEventListener('load', () => {
    const baseanimdur = getComputedStyle(window.parent.document.documentElement).getPropertyValue('--base-anim-dur').replace('s', '');
    const focusDelay = getComputedStyle(document.documentElement).getPropertyValue('--parent-grid-searchbox-focus-onload');
    setTimeout(() => {
        const inputValue = localStorage.getItem("myInputFocused_box1") || "";
        const inputNumber = inputValue.match(/\d+/)?.[0];
        const input = inputNumber ? document.querySelectorAll(".box-ipt")[inputNumber - 1] : document.querySelectorAll(".box-ipt")[0];
        input.focus();
    }, baseanimdur / focusDelay);
});

// Function on get active input on Search BT click in order to if input box empty then BT click goes back to focused box

window.getActiveInputOnBTClick = () => {
    const inputNumber = localStorage.getItem("myInputFocused_box1").match(/\d+/)?.[0];
    const input = inputNumber ? document.querySelectorAll(".box-ipt")[inputNumber - 1] : document.querySelectorAll(".box-ipt")[0];
    input.focus();
};

/////////////// REFOCUS WHEN CLICKING BODY ( EMPTY SPACE ) ///////////////

window.addEventListener('load', () => {
    const body = document.querySelector('body');
    document.addEventListener('click', event => {
        event.composedPath().includes(body) ? getActiveInputOnBTClick() : getActiveInputOnBTClick();
    });
});

/////////////// Set local storage item for memorizing last focus

window.addEventListener('load', () => {
    const values = ['input_1', 'input_2', 'input_3', 'input_4', 'input_5', 'input_6', 'input_7', 'input_8'];
    document.querySelectorAll('.box-ipt').forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box1', values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
  });
j0pj023g

j0pj023g1#

我认为你应该利用forEach循环中的"index"来完成这个任务,当你使用querySelectorAll来获取一个页面中的所有inputs时,你收到的数组会按照元素在页面上出现的顺序来索引每个元素。
您可以简单地将索引保存到本地存储器中,然后在加载页面时对该元素调用focus(),这样可以扩展到无限的输入。
我无法使用localStorage制作代码片段-但请尝试在本地运行此代码片段:

//wait for page to load
window.addEventListener("load", () => {
  //get all the Input elements on the page.
  const inputEls = [...document.querySelectorAll("input")];
  //set our focusPosition to either 0, or the localStorage Variable
  const lastFocus = Number(localStorage.getItem("lastFocus")) || 0;
  //iterate over each input element, using 'i' for the index
  inputEls.forEach((el, i) => {
    //if the index is equal to the lastFocus variable, focus that element
    if (i == lastFocus) {
      el.focus();
    }
    //add an event listener using the index to save that number to local storage
    el.addEventListener("focus", () => {
      localStorage.setItem("lastFocus", Number(i));
    });
  });
});

这种解决方案适用于页面上的任何输入量,而无需任何特殊的命名或标记。
页面的HTML可以是

<input />
<input />
<input />
<input />
<input />
<input />
<input />

这样就行了。
编辑:
下面是这个例子中的codepen。我对codepen做的唯一修改是在页面加载后等待400ms来改变焦点-因为codepen会加载其他内容并在页面加载后窃取焦点。单击任何输入,然后刷新页面-输入将重新聚焦。https://codepen.io/brandonetter/pen/PoBzWQd

7eumitmz

7eumitmz2#

正如布兰登所写的,你可以只使用forEach循环的可选参数index来获得输入在列表中的索引,要实现和前面一样的行为,只需从索引中构造名称'input_n',方法是加1。
通过生成与以前完全相同的格式和编号,您不需要修改现有代码的其他部分。

window.addEventListener('load', () => {
    document.querySelectorAll('.box-ipt').forEach((input, index) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box1', 'input_' + (index + 1)));
});
gc0ot86w

gc0ot86w3#

目标

  • 但是我需要一种方法,当我向HTML代码添加更多输入框时,不必返回此代码并向变量添加更多元素,如“input_9”、“input_10”等。*
  • 基本上是一种让变量接受任意数量的“input_X”元素的方法(比如“input_∞”--我知道JS中不存在∞,只是表明一个观点)。*

换句话说,OP需要一个解决方案,其中任何<input>,无论是静态的(在页面加载时出现)还是动态的(通过编程添加到页面),都将在它被聚焦时做出React(“focus”事件的起源)。

解决方案-事件委派

在祖先元素上注册“焦点”事件(父元素、父元素的父元素等,一直到<body>document对象、window对象),通常在注册的祖先元素上触发事件时,会发生"event bubbling",其中事件原点¹是用户实际交互的元素,成为事件链最后一个阶段的开始。事件链就像是从事件源到祖先元素(包括其间的所有元素)的信号传递路径(只有彼此具有父/子关系的元素才具有共同的源和祖先)。参见图I

图I -事件链

| 阶段|从|至|方向|
| - ------|- ------|- ------|- ------|
| 捕获|祖先|来源|向下|
| 目标|两者|两者|枢轴|
| 气泡|来源|祖先|向上|
但在这些特定的情况下,我们有两种选择,因为“焦点”事件不会冒泡(这种情况并不常见,大多数事件实际上冒泡):
1.通过传递true作为.addEventListener()方法的第三个参数,让祖先监听“捕获”阶段(事件链中沿DOM树向下的部分)(参见图II)。
1.使用“focusin”事件,它只是带有冒泡的“focus”。

图II -倾听捕获阶段

document.addEventListener("focus", eventHandler, true);
                                               /* ⮤ Third parameter is false by default. */

事件处理程序(由被触发的注册事件调用的回调函数)必须设计为只调用祖先的特定原始元素组的特定行为,而排除所有其他元素。最好将事件处理程序视为注解源来理解,请参阅示例
如果事件委托按照前面的描述实现,那么当注册的事件被触发时,您将能够控制祖先元素的任何子元素的行为。

event.currentTarget

乌尔
平方英寸event.bubbles
示例

**注意:**Web存储API在SO上被阻止,因此以下堆栈代码段中的示例功能不全。若要查看功能示例,请转到此Plunker

一个

jfewjypa

jfewjypa4#

这起了作用:

window.addEventListener('load', () => {
    const [inputElements, values] = [document.querySelectorAll('.box-ipt'), []];
    inputElements.forEach((input, i) => {
        values.push(`input_${i + 1}`);
    });
    document.querySelectorAll('.box-ipt').forEach((input) =>
        input.onfocus = (event) =>
            localStorage.setItem('myInputFocused_box1',
                values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
});

相关问题