元素的name属性对于querySelectorAll不可见,并且不显示在其HTML中

问题描述

我要选择名称'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分钟后再次超越了我...;-)