DOM 在某些方面有点奇怪,处理属性的方式也不例外。有多种方法可以处理元素的属性。属性是指诸如 <div id="cool"></div>
中的 id
之类的东西。有时您需要 *设置* 它们。有时您需要 *获取* 它们。有时有特殊的辅助 API。有时没有。
在本文中,我将假设 el
是您 JavaScript 代码中的一个 DOM 元素。假设您已经执行了类似 const el = document.querySelector("#cool");
的操作并匹配了 <div id="cool">
或其他类似元素。
某些属性也是 DOM 对象本身的属性,因此,如果您需要设置 id
或 title
,您可以执行以下操作
el.id; // "cool"
el.title = "my title";
el.title; // "my title";
其他类似工作的属性包括 lang
、align
和所有主要事件,例如 onclick
。
然后有一些属性与这些类似,但嵌套更深。style
属性就是这样。如果您记录 el.style
,您将看到大量的 CSS 样式声明。您可以轻松地获取和设置它们
el.style.color = "red";
module.style.backgroundColor = "black";
您也可以通过这种方式获取计算后的颜色。如果您执行 module.style.color
希望立即获取元素的颜色,您可能无法获得它。为此,您需要执行以下操作
let style = window.getComputedStyle(el);
style.color; // whatever in CSS won out
但并非所有属性都像这样的第一类属性。
el['aria-hidden'] = true; // nope
这在设置属性方面“有效”,但它没有以正确的方式在 DOM 中设置它。相反,您必须使用适用于所有属性的通用 setter 和 getter 函数,例如
el.setAttribute("aria-hidden", true);
el.getAttribute("aria-hidden");
某些属性有特殊的辅助方法。最方便的是 用于类属性的 classList
。对于像这样的元素
<div class="module big"></div>
您将拥有
el.classList.value; // "module big"
el.classList.length; // 2
el.classList.add("cool"); // adds the class "cool", so "module big cool"
el.classList.remove("big"); // removes "big", so "module cool"
el.classList.toggle("big"); // adds "big" back, because it was missing (goes back and forth)
el.classList.contains("module"); // true
还有更多,classList
本身也像数组一样,因此您可以对其进行 forEach
等操作。这是使用类的强大理由,因为 DOM API 周围非常方便。
另一种具有特殊辅助方法的属性类型是 data-*
。假设您有
<div data-active="true" data-placement="top right" data-extra-words="hi">test</div>
您有 dataset
el.dataset;
/*
{
active: "true",
"placement", "top right"
*/
el.dataset.active; // "true"
el.dataset.extraWords; // "hi", note the conversion to camelCase
el.dataset.active = "false"; // setters work like this
我认为您需要添加以下示例
el.ariaHidden = true;
“…classList 本身也像数组一样,因此您可以对其进行 forEach 等操作”
我认为这句话有点误导,因为
classList
是一个 **实时 DOMTokenList 集合**,而不是真正的数组,因此,例如,您可以在其上使用forEach
方法,但您无法使用其他与数组相关的 方法,例如map
、filter
、reduce
等,除非先将其转换为真正的数组。然后,如果我们必须处理 SVG,我们还有 .setAttributeNS 和 .getAttributeNS…
el.setAttribute("aria-hidden", true);
和el.ariaHidden = true;
之间是否存在性能差异?其他需要考虑的因素
htmlFor
用于<label for="asdf">
backgroundColor
用于background-color
,但readOnly
不用于read-only
,contentEditable
不用于content-editable
el.checked = true
与el.setAttribute('checked', true)
el.classList
与el.className
可以,但为什么是el.dataset
而不是el.dataSet
或el.dataList
?我认为这篇文章可以更清晰。首先,将 DOM 属性称为属性而不是“属性”更有帮助,以避免任何混淆。正如您所说,许多属性在相应的 DOM 元素上作为属性映射,但它们实际上是截然不同的东西,这样想可能更有帮助,这样就不会显得那么奇怪。一些主要差异
属性值(通过
getAttribute
获取)始终是字符串。属性可以是任何类型(布尔值、数字、ClassList
等)。属性和属性名称并不总是匹配,原因有很多。例如,JavaScript 保留字 (
for
/htmlFor
) 和表单元素状态(复选框或单选按钮的checked
属性映射到defaultChecked
属性,而 checked 属性没有对应的属性)。值可能不匹配。URL 就是一个很好的例子。如前所述,在
<a>
元素中,href
属性只是 HTML 中的文字字符串,而相应的属性将是完全限定的 URL。通常,属性本身在基于浏览器的 JavaScript 中通常没有用,处理属性更有帮助。
我不确定是否应该为这篇文章开一个新主题,但我想知道,如何在 React 应用中处理
data-
属性?最近我在尝试传递一些data-
属性(例如<Button data-role="foo" />
)时遇到了一些问题,唯一的方法是处理类似以下内容:const Button = ({
...其他
}) => (
<button data-role={other['data-role']} />
);
还有更好的方法吗?
classList 不是数组,也不像数组那样工作。
它是一个 DOMTokenList,DOMTokenList.forEach 函数在 Internet Explorer 中不可用。