问题描述
我要选择名称为'viewer'
的所有列表项。
这将返回一个空的NodeList
:
document.querySelectorAll('[name="viewer"]');
但这会返回一个包含正确项目的数组:
[...document.querySelectorAll('li')].filter(({ name }) => name == 'viewer');
列表项是这样创建的:
const listItem = document.createElement('li');
listItem.name = 'viewer';
listItem.id = 'viewer-1337';
当我在控制台中检查它们时,我在其HTML中看到了它们的id
,但没有看到它们的name
。例如
<li id="viewer-1337">foo</li>
似乎他们确实设置了name
属性,但是无法通过document.querySelectorAll
访问或在其HTML中可见。
为什么不呢?
const names = ['foo','bar'];
names.forEach(name => {
const li = document.createElement('li');
li.id = 'viewer-' + name;
li.name = 'viewer';
li.innerHTML = name;
const ul = document.querySelector('ul');
ul.appendChild(li);
});
const nodeList = document.querySelectorAll('[name="viewer"]');
console.log([...nodeList]);
const array = [...document.querySelectorAll('li')].filter(({ name }) => name == 'viewer');
console.log(array);
<ul></ul>
解决方法
之所以发生这种情况,是因为name
属性是reserved:
name获取或设置DOM中元素的name属性。它仅适用于以下元素:
<a>,<applet>,<button>,<form>,<frame>,<iframe>,<img>,<input>,<map>,<meta>,<object>,<param>,<select>,and <textarea>.
当您设置元素的name
属性(不是这些类型之一)时,该元素将 not 接收该值作为属性值。仍将其置于JavaScript对象的name
属性中,但不会将其置于属性中。
const div = document.createElement('div');
console.log(div.attributes.length);
div.name = 'foo';
console.log(div.attributes.length);
console.log(div.hasOwnProperty('name'));
因此查询字符串[name="viewer"]
不选择元素(因为它们不具有name
属性),但是[...document.querySelectorAll('li')].filter(({ name }) => name == 'viewer')
起作用是因为filter
回调已成功检索元素的JavaScript表示形式的name
属性。
您可以通过将其放入数据集中来对其进行修复:
const names = ['foo','bar'];
names.forEach(name => {
const li = document.createElement('li');
li.id = 'viewer-' + name;
li.dataset.name = 'viewer';
li.innerHTML = name;
const ul = document.querySelector('ul');
ul.appendChild(li);
});
const nodeList = document.querySelectorAll('[data-name="viewer"]');
console.log(nodeList.length);
<ul></ul>
,
由于li
元素没有name
属性,因此您不能使用CSS选择器来查找属性。只需使用data-name
属性即可。它可以按预期工作,如下所示:
const names = ['foo','bar'];
names.forEach(name => {
const li = document.createElement('li');
li.id = 'viewer-' + name;
li.dataset.name = 'viewer';
li.innerHTML = name;
const ul = document.querySelector('ul');
ul.appendChild(li);
});
const nodeList = document.querySelectorAll('[data-name=viewer]');
console.log(nodeList);
const array = [...document.querySelectorAll('li')].filter(({ name }) => name == 'viewer');
console.log(array);
<ul></ul>
是的,只是注意到@certainperformance在6分钟后再次超越了我...;-)