我如何在没有像 jQuery 这样的库的情况下操作 DOM?
How can I manipulate the DOM without a library like jQuery?
我习惯用jQuery来操纵DOM,例如:
var mything = $("#mything");
mything.on("click", function() {
mything.addClass("red");
mything.html("I have sinned.");
});
但现在我想用 Vanilla JavaScript 做同样的事情。这可能吗?我该怎么做?
Notice: This question is intended to be a comprehensive resource on Vanilla JavaScript DOM manipulation.
使用 Vanilla JS 操作文档对象模型时,您也将直接访问 Document
and Node
s. A document contains Element
s, particularly HTMLElement
s and SVGElement
s which are both Node
s. An Element
may contain Text
。
寻找元素
您可以获得与 CSS 选择器与 mynode.querySelector()
, and all elements that match the selector with myNode.querySelectorAll()
匹配的第一个元素。大多数时候 myNode
将是 Document
,因此您可以在文档中获取与选择器匹配的任何内容——但是,您只能查看节点的 descendants当 myNode
是一个元素时。
document.querySelectorAll('p:hover'); // Returns a NodeList of hovered paragraphs
这类似于 jQuery('p:hover')
。
还有更专业的方法,如:
myNode.getElementById()
myNode.getElementsByTagName()
myNode.getElementsByClassName()
myNode.getElementsByName()
具有不言自明的名称。注意 .getElementBy...
returns 是单个元素,而 .getElementsBy...
(复数元素s) returns a NodeList
, 即本质上是一个节点数组,但它没有标准的数组方法。
另请参阅:What's the best way to loop through a set of elements in JavaScript?
每个元素还可能有一个:
parentNode
previousSibling
previousElementSibling
(不包括文本节点)
nextSibling
nextElementSibling
(不包括文本节点)
firstChild
firstElementChild
(不包括文本节点)
lastChild
lastElementChild
(不包括文本节点)
childElementCount
(与children.length
相同)
和 NodeList
个:
childNodes
children
(不包括文本节点)
这样,我们就可以遍历DOM.
例如,要在此处获取 #clickme
的父元素中第一个段落元素的最后一个子元素:
document.getElementById('clickme').addEventListener('click', function() {
console.log(this.parentNode.getElementsByTagName('p')[0].lastChild);
});
<div>
<blockquote>This is a really great quote.</blockquote>
<p>This is a <em>really</em> interesting paragraph. <span>this will be selected</span></p>
<p>In fact, here's another!</p>
<button id="clickme">Click me!</button>
</div>
...您找到它的 parentNode
,在其上使用 getElementsByTagName
以仅获取段落后代,取其中的第一个,并获取其 lastChild
.
要获取其中包含的文本,您可以获取其文本节点(其第一个子节点),然后使用 text.wholeText
.
创建和删除
您可以使用 document.createElement('aTagName')
创建一个元素或使用 newElement = myElement.cloneNode()
克隆另一个元素。传递 cloneNode
true
作为第一个参数也复制其后代。不要克隆具有 ID 的元素,因为这会导致同一文档中出现 2 个具有相同 ID 的元素。
然后您可以使用 parent.appendChild(newElement)
or append it after another element with parent.insertBefore(newElement, referenceElement)
将新元素(或现有元素)附加到父元素。 insertAfter
方法不存在,但可以创建:
HTMLElement.prototype.insertAfter = function(newEl, refEl) {
if (refEl.nextSibling) refEl.parentNode.insertBefore(newEl, refEl.nextSibling);
else refEl.parentNode.appendChild(newEl);
};
一个节点可以用parent.removeChild()
or replaced with parent.replaceChild(newChild)
or just removed inline with mynode.remove()
删除。
function poof() {
this.remove();
}
var elements = document.getElementsByClassName('poof');
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', poof);
}
<span class="poof">hi,</span>
<span class="poof">click</span>
<span class="poof">to</span>
<span class="poof">delete</span>
<span class="poof">me;</span>
<span class="poof">it</span>
<span class="poof">was</span>
<span class="poof">fun</span>
<span class="poof">being</span>
<span class="poof">a</span>
<span class="poof">span</span>
类 和样式
"and styles," 我的意思是 class。 样式适用于 CSS. 您只能将 CSS 样式应用到添加了 class 和 JavaScript 的元素。1
HTML 中的元素有一个 classList
property which is a DOMTokenList
表示 space 分隔的 属性,在本例中为 class
。您可以在 class 列表中 .add()
、.remove()
和 .toggle()
class 或检查它是否 .contains()
和 class。
document.getElementById('clickme').addEventListener('click', function() {
document.getElementById('colors').classList.toggle('green');
});
.green { color: green }
<div id="colors">hello!</div>
<button id="clickme">Click me!</button>
属性
可以使用 querySelector
和 querySelectorAll
选择具有特定属性的元素。大多数属性都是您正在使用的元素的属性。例如:
myDiv.hidden = true; // Hides element from view and from screenreaders
但如果不是,则可以使用 getAttributeNode
, setAttributeNode
, and removeAttributeNode
访问任何属性。属性节点有 ownerElements 和 values.
"data-*" 属性可以用 myelement.dataset
访问。例如,mydiv.dataset.pie = 'yummy'
会将 data-pie="yummy"
添加到 div.
事件
事件稍微复杂一些。 绑定一个(如jQuery('selector').on
)非常简单:
myElement.addEventListener('event-name', afunction);
(其他对象也有此方法——例如window
)
事件也可以删除:
myelement.removeEventListener('event-name', afunction);
可以找到事件列表 here。
传递给 addEventListener
的函数将传递事件发生的参数,并具有事件侦听器 绑定 元素的 this
到.
然而,事件并没有这么简单:像单击按钮这样微不足道的事情可能会针对不同的元素和不同的事件触发许多事件侦听器。
– Browser Input Events: Can We Do Better Than The Click? 来自 Smashing Magazine
另请参阅:What is event bubbling and capturing?
1如果确实需要用JS修改一个样式,使用myElement.style.styleProperty = 'value'
更改内联样式属性.
我习惯用jQuery来操纵DOM,例如:
var mything = $("#mything");
mything.on("click", function() {
mything.addClass("red");
mything.html("I have sinned.");
});
但现在我想用 Vanilla JavaScript 做同样的事情。这可能吗?我该怎么做?
Notice: This question is intended to be a comprehensive resource on Vanilla JavaScript DOM manipulation.
使用 Vanilla JS 操作文档对象模型时,您也将直接访问 Document
and Node
s. A document contains Element
s, particularly HTMLElement
s and SVGElement
s which are both Node
s. An Element
may contain Text
。
寻找元素
您可以获得与 CSS 选择器与 mynode.querySelector()
, and all elements that match the selector with myNode.querySelectorAll()
匹配的第一个元素。大多数时候 myNode
将是 Document
,因此您可以在文档中获取与选择器匹配的任何内容——但是,您只能查看节点的 descendants当 myNode
是一个元素时。
document.querySelectorAll('p:hover'); // Returns a NodeList of hovered paragraphs
这类似于 jQuery('p:hover')
。
还有更专业的方法,如:
myNode.getElementById()
myNode.getElementsByTagName()
myNode.getElementsByClassName()
myNode.getElementsByName()
具有不言自明的名称。注意 .getElementBy...
returns 是单个元素,而 .getElementsBy...
(复数元素s) returns a NodeList
, 即本质上是一个节点数组,但它没有标准的数组方法。
另请参阅:What's the best way to loop through a set of elements in JavaScript?
每个元素还可能有一个:
parentNode
previousSibling
previousElementSibling
(不包括文本节点)nextSibling
nextElementSibling
(不包括文本节点)firstChild
firstElementChild
(不包括文本节点)lastChild
lastElementChild
(不包括文本节点)childElementCount
(与children.length
相同)
和 NodeList
个:
childNodes
children
(不包括文本节点)
这样,我们就可以遍历DOM.
例如,要在此处获取 #clickme
的父元素中第一个段落元素的最后一个子元素:
document.getElementById('clickme').addEventListener('click', function() {
console.log(this.parentNode.getElementsByTagName('p')[0].lastChild);
});
<div>
<blockquote>This is a really great quote.</blockquote>
<p>This is a <em>really</em> interesting paragraph. <span>this will be selected</span></p>
<p>In fact, here's another!</p>
<button id="clickme">Click me!</button>
</div>
...您找到它的 parentNode
,在其上使用 getElementsByTagName
以仅获取段落后代,取其中的第一个,并获取其 lastChild
.
要获取其中包含的文本,您可以获取其文本节点(其第一个子节点),然后使用 text.wholeText
.
创建和删除
您可以使用 document.createElement('aTagName')
创建一个元素或使用 newElement = myElement.cloneNode()
克隆另一个元素。传递 cloneNode
true
作为第一个参数也复制其后代。不要克隆具有 ID 的元素,因为这会导致同一文档中出现 2 个具有相同 ID 的元素。
然后您可以使用 parent.appendChild(newElement)
or append it after another element with parent.insertBefore(newElement, referenceElement)
将新元素(或现有元素)附加到父元素。 insertAfter
方法不存在,但可以创建:
HTMLElement.prototype.insertAfter = function(newEl, refEl) {
if (refEl.nextSibling) refEl.parentNode.insertBefore(newEl, refEl.nextSibling);
else refEl.parentNode.appendChild(newEl);
};
一个节点可以用parent.removeChild()
or replaced with parent.replaceChild(newChild)
or just removed inline with mynode.remove()
删除。
function poof() {
this.remove();
}
var elements = document.getElementsByClassName('poof');
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', poof);
}
<span class="poof">hi,</span>
<span class="poof">click</span>
<span class="poof">to</span>
<span class="poof">delete</span>
<span class="poof">me;</span>
<span class="poof">it</span>
<span class="poof">was</span>
<span class="poof">fun</span>
<span class="poof">being</span>
<span class="poof">a</span>
<span class="poof">span</span>
类 和样式
"and styles," 我的意思是 class。 样式适用于 CSS. 您只能将 CSS 样式应用到添加了 class 和 JavaScript 的元素。1
HTML 中的元素有一个 classList
property which is a DOMTokenList
表示 space 分隔的 属性,在本例中为 class
。您可以在 class 列表中 .add()
、.remove()
和 .toggle()
class 或检查它是否 .contains()
和 class。
document.getElementById('clickme').addEventListener('click', function() {
document.getElementById('colors').classList.toggle('green');
});
.green { color: green }
<div id="colors">hello!</div>
<button id="clickme">Click me!</button>
属性
可以使用 querySelector
和 querySelectorAll
选择具有特定属性的元素。大多数属性都是您正在使用的元素的属性。例如:
myDiv.hidden = true; // Hides element from view and from screenreaders
但如果不是,则可以使用 getAttributeNode
, setAttributeNode
, and removeAttributeNode
访问任何属性。属性节点有 ownerElements 和 values.
"data-*" 属性可以用 myelement.dataset
访问。例如,mydiv.dataset.pie = 'yummy'
会将 data-pie="yummy"
添加到 div.
事件
事件稍微复杂一些。 绑定一个(如jQuery('selector').on
)非常简单:
myElement.addEventListener('event-name', afunction);
(其他对象也有此方法——例如window
)
事件也可以删除:
myelement.removeEventListener('event-name', afunction);
可以找到事件列表 here。
传递给 addEventListener
的函数将传递事件发生的参数,并具有事件侦听器 绑定 元素的 this
到.
然而,事件并没有这么简单:像单击按钮这样微不足道的事情可能会针对不同的元素和不同的事件触发许多事件侦听器。
– Browser Input Events: Can We Do Better Than The Click? 来自 Smashing Magazine
另请参阅:What is event bubbling and capturing?
1如果确实需要用JS修改一个样式,使用myElement.style.styleProperty = 'value'
更改内联样式属性.