当其中一个子节点具有 name="children" 时,不能使用 Element.children
Can't use Element.children when one of the child nodes has name="children"
我在使用 Element.children 时注意到一个奇怪的问题,似乎没有找到好的解决方法。
示例 1(预期行为)
拿这个HTML:
<form>
<input name="hi">
<input name="bye">
</form>
还有这个 JS
const formElement = document.querySelector('form');
for (let i = 0; i < formElement.children.length; i++) {
console.log(formElement.children[i].name);
}
控制台打印出如下内容,如您所料:
"hi"
"bye"
示例 2(奇怪的行为)
现在,让我们添加一个带有 name="children"
的输入字段
<form>
<input name="hi">
<input name="bye">
<input name="children">
</form>
控制台不打印任何内容。
我认为为什么会这样
formElement.children
return 一个 HTML 集合。
在 HTML 集合中,您可以通过索引访问子元素,或直接通过您尝试定位的元素的名称属性访问。
因此,为了获得 "hi" 元素,您可以说 formElement.children[0]
或 formElement.hi
.
但是当集合中有名称为"children"
的元素时,formElement.children
将return名称为“children”的元素,并且不再有任何办法遍历所有元素。
我该如何解决这个问题?
这是我的问题。我知道我不能简单地不使用“children”这个名字而选择其他名字,但肯定有一种方法可以使它起作用?
这里提笔说明问题:https://codepen.io/pwkip/pen/XWVoXVE
编辑:
这似乎与 formElement 是一个 <form>
这一事实有关。当我将其更改为 <div>
时,一切正常。所以我想问题归结为:
如何将 HTMLFormElement 转换为常规 HTMLElement?
这是因为非常不幸的历史原因,HTMLFormElement 有一个 named property getter, which will return 子 <input>
元素,它们有 .name
或 .id
属性 值设置为给定名称。 实际上它比那更复杂,但没那么有趣。
以我的愚见,这确实是规范中的一个怪癖,但如果不破坏旧网站就无法删除它,这是规范作者不太喜欢的。
所以是的,这个 named
getter 将优先于原型链中继承的任何其他 getter。
如果您真的不想更改元素的 name
,您可以在 HTMLFormElement 上显式调用 Element.children
getter,或者更简单的方法可能只是使用 .querySelectorAll("*")
(假设您没有具有此类名称或 ID 的元素;-)
const form = document.querySelector("form");
console.log("with .children:", form.children); // our <input>
const getter = Object.getOwnPropertyDescriptor(Element.prototype, "children").get;
console.log("with Element's getter:", getter.call(form)); // an HTMLCollection
console.log("with querySelectorAll:", form.querySelectorAll("*")); // a NodeList
<form>
<input name="foo">
<input name="children">
</form>
我在使用 Element.children 时注意到一个奇怪的问题,似乎没有找到好的解决方法。
示例 1(预期行为)
拿这个HTML:
<form>
<input name="hi">
<input name="bye">
</form>
还有这个 JS
const formElement = document.querySelector('form');
for (let i = 0; i < formElement.children.length; i++) {
console.log(formElement.children[i].name);
}
控制台打印出如下内容,如您所料:
"hi"
"bye"
示例 2(奇怪的行为)
现在,让我们添加一个带有 name="children"
<form>
<input name="hi">
<input name="bye">
<input name="children">
</form>
控制台不打印任何内容。
我认为为什么会这样
formElement.children
return 一个 HTML 集合。
在 HTML 集合中,您可以通过索引访问子元素,或直接通过您尝试定位的元素的名称属性访问。
因此,为了获得 "hi" 元素,您可以说 formElement.children[0]
或 formElement.hi
.
但是当集合中有名称为"children"
的元素时,formElement.children
将return名称为“children”的元素,并且不再有任何办法遍历所有元素。
我该如何解决这个问题?
这是我的问题。我知道我不能简单地不使用“children”这个名字而选择其他名字,但肯定有一种方法可以使它起作用?
这里提笔说明问题:https://codepen.io/pwkip/pen/XWVoXVE
编辑:
这似乎与 formElement 是一个 <form>
这一事实有关。当我将其更改为 <div>
时,一切正常。所以我想问题归结为:
如何将 HTMLFormElement 转换为常规 HTMLElement?
这是因为非常不幸的历史原因,HTMLFormElement 有一个 named property getter, which will return 子 <input>
元素,它们有 .name
或 .id
属性 值设置为给定名称。 实际上它比那更复杂,但没那么有趣。
以我的愚见,这确实是规范中的一个怪癖,但如果不破坏旧网站就无法删除它,这是规范作者不太喜欢的。
所以是的,这个 named
getter 将优先于原型链中继承的任何其他 getter。
如果您真的不想更改元素的 name
,您可以在 HTMLFormElement 上显式调用 Element.children
getter,或者更简单的方法可能只是使用 .querySelectorAll("*")
(假设您没有具有此类名称或 ID 的元素;-)
const form = document.querySelector("form");
console.log("with .children:", form.children); // our <input>
const getter = Object.getOwnPropertyDescriptor(Element.prototype, "children").get;
console.log("with Element's getter:", getter.call(form)); // an HTMLCollection
console.log("with querySelectorAll:", form.querySelectorAll("*")); // a NodeList
<form>
<input name="foo">
<input name="children">
</form>