是否开发了使用setAttribute
而不是点 ( .
) 属性表示法的最佳实践?
例如:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
或者
myObj.className = "nameOfClass";
myObj.id = "someID";
是否开发了使用setAttribute
而不是点 ( .
) 属性表示法的最佳实践?
例如:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
或者
myObj.className = "nameOfClass";
myObj.id = "someID";
来自Javascript: The Definitive Guide,它阐明了一些事情。它指出HTML 文档的HTMLElement对象定义了与所有标准 HTML 属性相对应的 JS 属性。
所以你只需要setAttribute
用于非标准属性。
例子:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
以前的答案都不完整,而且大多数都包含错误信息。
在 JavaScript中访问 DOM元素的属性有三种方式。只要您了解如何使用它们,这三种方法都可以在现代浏览器中可靠地工作。
element.attributes
元素具有返回Attr对象的实时NamedNodeMap的属性attributes 。此集合的索引可能因浏览器而异。因此,订单无法保证。具有添加和删除属性的方法(分别为和)。NamedNodeMap
getNamedItem
setNamedItem
请注意,尽管 XML 明确区分大小写,但 DOM 规范要求对字符串名称进行规范化,因此传递给getNamedItem
的名称实际上是不区分大小写的。
var div = document.getElementsByTagName('div')[0];
//you can look up specific attributes
var classAttr = div.attributes.getNamedItem('CLASS');
document.write('attributes.getNamedItem() Name: ' + classAttr.name + ' Value: ' + classAttr.value + '<br>');
//you can enumerate all defined attributes
for(var i = 0; i < div.attributes.length; i++) {
var attr = div.attributes[i];
document.write('attributes[] Name: ' + attr.name + ' Value: ' + attr.value + '<br>');
}
//create custom attribute
var customAttr = document.createAttribute('customTest');
customAttr.value = '567';
div.attributes.setNamedItem(customAttr);
//retreive custom attribute
customAttr = div.attributes.getNamedItem('customTest');
document.write('attributes.getNamedItem() Name: ' + customAttr.name + ' Value: ' + customAttr.value + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
element.getAttribute
&element.setAttribute
这些方法直接存在于Element
不需要访问attributes
其方法但执行相同功能的情况下。
同样,请注意字符串名称不区分大小写。
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.getAttribute('class') + '<br>');
document.write('Name: ID Value: ' + div.getAttribute('ID') + '<br>');
document.write('Name: DATA-TEST Value: ' + div.getAttribute('DATA-TEST') + '<br>');
document.write('Name: nonStandard Value: ' + div.getAttribute('nonStandard') + '<br>');
//create custom attribute
div.setAttribute('customTest', '567');
//retreive custom attribute
document.write('Name: customTest Value: ' + div.getAttribute('customTest') + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
element.id
可以使用 DOM 对象上的便利属性来访问许多属性。给定对象上存在哪些属性取决于对象的 DOM 节点类型,而不管 HTML 中指定了哪些属性。可用属性在相关 DOM 对象的原型链中的某处定义。因此,定义的特定属性将取决于您正在访问的 Element 的类型。
例如,className
andid
定义Element
并存在于所有作为元素的 DOM 节点上,但不是文本或注释节点。value
定义更狭隘。它仅适用于HTMLInputElement
它的后代。
请注意,JavaScript 属性区分大小写。虽然大多数属性将使用小写,但有些是驼峰式。因此,请务必检查规格以确定。
这个“图表”捕获了这些 DOM 对象的原型链的一部分。它甚至还没有接近完成,但它展示了整体结构。
____________Node___________
| | |
Element Text Comment
| |
HTMLElement SVGElement
| |
HTMLInputElement HTMLSpanElement
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.className + '<br>');
document.write('Name: id Value: ' + div.id + '<br>');
document.write('Name: ID Value: ' + div.ID + '<br>'); //undefined
document.write('Name: data-test Value: ' + div.dataset.test + '<br>'); //.dataset is a special case
document.write('Name: nonStandard Value: ' + div.nonStandard + '<br>'); //undefined
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
警告:这是对 HTML 规范如何定义属性以及现代常青浏览器如何处理它们的解释。肯定有一些旧的浏览器(IE、Netscape 等)不遵守甚至早于该规范。如果您需要支持旧的(损坏的)浏览器,您将需要比此处提供的更多信息。
如果您想在 JavaScript 中进行编程访问,则应始终使用直接.attribute
形式(但请参阅下面的 quirksmode 链接)。它应该正确处理不同类型的属性(想想“onload”)。
当您希望按原样处理 DOM 时使用getAttribute
/ (例如,仅限文字文本)。setAttribute
不同的浏览器混淆了两者。请参阅Quirks 模式:attribute (in)compatibility。
我发现setAttribute
有必要的一种情况是在更改 ARIA 属性时,因为没有相应的属性。例如
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
没有x.arialabel
或类似的东西,所以你必须使用 setAttribute。
编辑:x["aria-label"] 不起作用。你真的需要setAttribute。
x.getAttribute('aria-label')
null
x["aria-label"] = "Test"
"Test"
x.getAttribute('aria-label')
null
x.setAttribute('aria-label', 'Test2')
undefined
x["aria-label"]
"Test"
x.getAttribute('aria-label')
"Test2"
这些答案并没有真正解决properties和attributes之间的巨大混淆。此外,根据 Javascript 原型,有时您可以使用元素的属性来访问属性,有时则不能。
首先,您必须记住 anHTMLElement
是一个 Javascript 对象。像所有对象一样,它们具有属性。当然,您可以创建一个几乎可以在内部调用任何内容的属性HTMLElement
,但它不必对 DOM(页面上的内容)做任何事情。点符号 ( .
) 用于属性。现在,有一些映射到属性的特殊属性,在当时或写作时,只有 4 个是保证的(稍后会详细介绍)。
所有HTMLElement
s 都包含一个名为 的属性attributes
。HTMLElement.attributes
是与 DOM 中的元素相关的活动对象。 NamedNodeMap
“实时”意味着当 DOM 中的节点发生变化时,它们会在 JavaScript 端发生变化,反之亦然。在这种情况下,DOM 属性是有问题的节点。ANode
具有.nodeValue
您可以更改的属性。NamedNodeMap
对象有一个调用函数setNamedItem
,您可以在其中更改整个节点。您也可以通过密钥直接访问节点。例如,可以说.attributes["dir"]
which is the same as .attributes.getNamedItem('dir');
(Side note, NamedNodeMap
is case-insensitive, so you can also pass 'DIR'
);
直接有一个类似的函数HTMLElement
,您可以直接调用它,如果它不存在setAttribute
,它将自动创建一个节点nodeValue
并设置. 还有一些属性可以HTMLElement
通过特殊属性直接作为属性访问,例如dir
. 这是它的外观的粗略映射:
HTMLElement {
attributes: {
setNamedItem: function(attr, newAttr) {
this[attr] = newAttr;
},
getNamedItem: function(attr) {
return this[attr];
},
myAttribute1: {
nodeName: 'myAttribute1',
nodeValue: 'myNodeValue1'
},
myAttribute2: {
nodeName: 'myAttribute2',
nodeValue: 'myNodeValue2'
},
}
setAttribute: function(attr, value) {
let item = this.attributes.getNamedItem(attr);
if (!item) {
item = document.createAttribute(attr);
this.attributes.setNamedItem(attr, item);
}
item.nodeValue = value;
},
getAttribute: function(attr) {
return this.attributes[attr] && this.attributes[attr].nodeValue;
},
dir: // Special map to attributes.dir.nodeValue || ''
id: // Special map to attributes.id.nodeValue || ''
className: // Special map to attributes.class.nodeValue || ''
lang: // Special map to attributes.lang.nodeValue || ''
}
因此,您可以通过 6 种方式更改dir
属性:
// 1. Replace the node with setNamedItem
const newAttribute = document.createAttribute('dir');
newAttribute.nodeValue = 'rtl';
element.attributes.setNamedItem(newAttribute);
// 2. Replace the node by property name;
const newAttribute2 = document.createAttribute('dir');
newAttribute2.nodeValue = 'rtl';
element.attributes['dir'] = newAttribute2;
// OR
element.attributes.dir = newAttribute2;
// 3. Access node with getNamedItem and update nodeValue
// Attribute must already exist!!!
element.attributes.getNamedItem('dir').nodeValue = 'rtl';
// 4. Access node by property update nodeValue
// Attribute must already exist!!!
element.attributes['dir'].nodeValue = 'rtl';
// OR
element.attributes.dir.nodeValue = 'rtl';
// 5. use setAttribute()
element.setAttribute('dir', 'rtl');
// 6. use the UNIQUELY SPECIAL dir property
element["dir"] = 'rtl';
element.dir = 'rtl';
您可以使用方法 #1-5 更新所有属性,但只能使用dir
、id
、lang
和className
方法 #6。
HTMLElement
有这4个特殊属性。一些元素是HTMLElement
具有更多映射属性的扩展类。例如,HTMLAnchorElement
有HTMLAnchorElement.href
、HTMLAnchorElement.rel
和HTMLAnchorElement.target
。但是,请注意,如果您在没有这些特殊属性的元素上设置这些属性(例如在 a 上HTMLTableElement
),则属性不会更改,它们只是普通的自定义属性。为了更好地理解,这里有一个继承的例子:
HTMLAnchorElement extends HTMLElement {
// inherits all of HTMLElement
href: // Special map to attributes.href.nodeValue || ''
target: // Special map to attributes.target.nodeValue || ''
rel: // Special map to attributes.ref.nodeValue || ''
}
现在大警告:像所有 Javascript 对象一样,您可以添加自定义属性。但是,这些不会改变 DOM 上的任何内容。你可以做:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
但这与
newElement.myCustomDisplayAttribute = 'block';
这意味着添加自定义属性不会链接到.attributes[attr].nodeValue
.
表现
我已经构建了一个 jsperf 测试用例来显示差异:https ://jsperf.com/set-attribute-comparison 。基本上,按顺序:
dir
, id
, className
)。element.attributes.ATTRIBUTENAME.nodeValue =
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
结论(TL;DR)
HTMLElement
使用来自: element.dir
、element.id
、 element.className
或的特殊属性映射element.lang
。
如果您 100% 确定该元素是HTMLElement
具有特殊属性的扩展,请使用该特殊映射。(您可以检查if (element instanceof HTMLAnchorElement)
)。
如果您 100% 确定该属性已经存在,请使用element.attributes.ATTRIBUTENAME.nodeValue = newValue
.
如果没有,请使用setAttribute()
.
“何时在 JavaScript 中使用 setAttribute 与 .attribute=?”
一般规则是使用.attribute
并检查它是否适用于浏览器。
..如果它在浏览器上工作,你很高兴。
..如果没有,请使用而.setAttribute(attribute, value)
不是该属性。.attribute
对所有属性重复冲洗。
好吧,如果你很懒,你可以简单地使用.setAttribute
. 这在大多数浏览器上应该可以正常工作。(虽然支持的浏览器.attribute
可以比它更好地优化它.setAttribute(attribute, value)
。)
这看起来像是使用 setAttribute 更好的一种情况:
var posElem = document.getElementById('animation');
var newStyle = 'background: ' + newBack + ';' +
'color: ' + newColor + ';' +
'border: ' + newBorder + ';';
if(typeof(posElem.style.cssText) != 'undefined') {
posElem.style.cssText = newStyle;
} else {
posElem.setAttribute('style', newStyle);
}
在元素上设置属性(例如类)的方法: 1. el.className = string 2. el.setAttribute('class',string) 3. el.attributes.setNamedItem(object) 4. el.setAttributeNode(node)
我做了一个简单的基准测试(这里)
似乎 setAttributeNode 比使用 setAttribute 快 3 倍。
所以如果性能是一个问题 - 使用“setAttributeNode”
Google API 脚本中关于此的有趣内容:
他们这样做:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
请注意,它们如何setAttribute
用于“src”和“nonce”,然后.async = ...
用于“async”属性。
我不是 100% 确定,但这可能是因为“异步”仅在支持直接.attr =
分配的浏览器上受支持。因此,尝试这样做是没有意义的,sestAttribute("async")
因为如果浏览器不理解.async=...
- 它不会理解“异步”属性。
希望这是我正在进行的“Un-minify GAPI”研究项目的有用见解。如我错了请纠正我。
这是非常好的讨论。当我希望或可以说希望(我可能会成功添加)重新发明轮子时,我曾经有过这样的时刻。上面的任何方法都是很好的讨论,所以任何人来这里寻找元素属性和属性之间的区别。这是我的一分钱,我确实必须努力找到它。我会保持简单,所以没有特别的技术术语。
假设我们有一个名为“A”的变量。我们习惯的如下。
下面会抛出一个错误,因为简单地说它是一种只能具有一个属性的对象,即奇异的左侧 = 奇异的右侧对象。其他所有东西都被忽略并扔进垃圾箱。
let A = 'f';
A.b =2;
console.log(A.b);
谁决定它必须是单数=单数。制定 JavaScript 和 html 标准的人,这就是引擎的工作方式。
让我们换个例子。
let A = {};
A.b =2;
console.log(A.b);
这次它起作用了......因为我们已经明确告诉它,谁决定我们可以在这种情况下告诉它,但不能在以前的情况下。同样是制定 JavaScript 和 html 标准的人。
我希望我们能解决这个问题,让它进一步复杂化
let A = {};
A.attribute ={};
A.attribute.b=5;
console.log(A.attribute.b); // will work
console.log(A.b); // will not work
我们所做的是第 1 层的树,然后是非奇异对象的子层。除非你知道什么在哪里并调用它,否则它会起作用。
这就是 HTMLDOM 在为每个 HTML 元素创建解析和绘制的 DOM 树时所发生的事情。每个人都有每个说的属性级别。有些是预定义的,有些不是。这就是 ID 和 VALUE 位出现的地方。在幕后,它们在 1 级属性和太阳级属性(即属性)之间以 1:1 的比例映射。因此,改变一个会改变另一个。这是对象获取器和设置器方案的作用。
let A = {
attribute :{
id:'',
value:''
},
getAttributes: function (n) {
return this.attribute[n];
},
setAttributes: function (n,nn){
this.attribute[n] = nn;
if(this[n]) this[n] = nn;
},
id:'',
value:''
};
A.id = 5;
console.log(A.id);
console.log(A.getAttributes('id'));
A.setAttributes('id',7)
console.log(A.id);
console.log(A.getAttributes('id'));
A.setAttributes('ids',7)
console.log(A.ids);
console.log(A.getAttributes('ids'));
A.idsss=7;
console.log(A.idsss);
console.log(A.getAttributes('idsss'));
这就是上面显示的点,ELEMENTS 有另一组所谓的属性列表属性,它有自己的主要属性。两者之间有一些预定义的属性,并被映射为 1:1,例如 ID 对每个人都是通用的,但值不是,src 也不是。当解析器到达那个点时,它会简单地提取字典,了解什么时候出现这样那样的东西。
所有元素都有属性和属性,并且它们之间的一些项目是通用的。一个中常见的东西在另一个中并不常见。
在 HTML3 的旧时代,我们先使用 html,然后再使用 JS。现在,它反过来了,因此使用内联 onlclick 变得如此可恶。事情在 HTML5 中向前发展,其中有许多可作为集合访问的属性列表,例如类、样式。在过去,颜色是一个属性,现在移到 css 进行处理不再是有效属性。
Element.attributes 是 Element 属性中的子属性列表。
除非您可以更改 Element 属性的 getter 和 setter,这几乎是不可能的,因为它会破坏所有功能通常不能立即写入,因为我们将某些东西定义为 A.item 并不一定意味着 Js 引擎也会运行另一个将其添加到 Element.attributes.item 的函数行。
我希望这能在澄清什么是什么方面取得进展。为此,我尝试了 Element.prototype.setAttribute 与自定义函数,它只是打破了整个事情,因为它覆盖了设置属性函数在幕后播放的原生函数。
再添加 2 个与.textContent
和相关的点.innerHTML
<div id="mydiv"></div>
var elem = document.getElementById("mydiv");
elem.textContent = "hello"; // OK - Content has been updated
elem.setAttribute("textContent", "hello"); // NOT OK - You are trying to set
// the attribute than it's content
elem.innerHTML = "world"; // OK - Content has been updated
elem.setAttribute("innerHTML", "world"); // NOT OK - You are trying to set
// the attribute than it's content
两者之间的一个区别是 setAttribute,当用于设置value
an<input/>
时,将在您调用.reset()
它所属的表单时将其设为默认值,但.value =
不会这样做。
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
请注意,如果调用 setAttribute() 来设置特定属性的值,则后续调用 reset() 不会将该属性重置为其默认值,而是将属性保持在 setAttribute() 调用设置的任何值它到。