如果没有像 jQuery 这样的库,我如何操作 DOM? [关闭]

Posted

技术标签:

【中文标题】如果没有像 jQuery 这样的库,我如何操作 DOM? [关闭]【英文标题】:How can I manipulate the DOM without a library like jQuery? [closed] 【发布时间】:2022-01-22 04:37:42 【问题描述】:

我习惯使用jQuery来操作DOM,例如:

var mything = $("#mything");
mything.on("click", function() 
    mything.addClass("red");
    mything.html("I have sinned.");
);

但现在我想用 Vanilla javascript 做同样的事情。这可能吗?我该怎么做?

注意:此问题旨在成为有关 Vanilla JavaScript DOM 操作的综合资源。

【问题讨论】:

您是否有一些问题将作为重复本关闭? @Bergi 任何与基本 DOM 操作相关的东西。就像“点击某物时如何在某处更改文本?”或“为什么 document.getElementsByClassName().forEach 不起作用?”或类似的。 What do people mean when they say "DOM Manipulation"? 的可能重复项 @Qantas94Heavy 不,这几乎没有相关性 @bjb568:你问的是如何操作 DOM。该问题回答了您的“规范”问题。 【参考方案1】:

使用 Vanilla JS 操作文档对象模型时,您将直接访问 DocumentNodes。一个文档包含Elements,特别是HTMLElements 和SVGElements,它们都是Nodes。 Element 也可能包含 Text

寻找元素

您可以获得第一个与mynode.querySelector() 匹配的CSS 选择器的元素,以及与myNode.querySelectorAll() 匹配选择器的所有 元素。大多数情况下myNode 将是Document,因此您可以在文档中获得与选择器匹配的任何内容 - 但是,当myNode 是一个节点时,您只能查看节点的后代元素。

document.querySelectorAll('p:hover'); // Returns a NodeList of hovered paragraphs

这类似于jQuery('p:hover')

还有更专业的方法,例如:

myNode.getElementById() myNode.getElementsByTagName() myNode.getElementsByClassName() myNode.getElementsByName()

具有不言自明的名称。请注意,.getElementBy... 返回单个元素,而.getElementsBy...(复数元素s)返回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

还有NodeLists 的:

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) 将新元素(或现有元素)附加到父元素,或使用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() 删除节点,或者使用parent.replaceChild(newChild) 替换节点,或者直接使用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>

类和样式

“和样式”是指类。 样式用于 CSS。您只能将 CSS 样式应用于已使用 JavaScript 添加了类的元素。1

HTML 中的元素有一个classList 属性,它是一个DOMTokenList,表示以空格分隔的属性,在本例中为class。你可以在classList中.add().remove().toggle()类或者检查.contains()是不是一个类。

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>

属性

可以使用querySelectorquerySelectorAll 选择具有某些属性的元素。大多数属性是您正在使用的元素的属性。例如:

myDiv.hidden = true; // Hides element from view and from screenreaders

但如果不是,则可以使用getAttributeNodesetAttributeNoderemoveAttributeNode 访问任何属性。 AttributeNodes 有 ownerElementsvalues。

“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);

见:removeEventListener

活动列表可以在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 方法的等价物,那么对于新手来说,这将更容易接受。 @Qantas94Heavy 我在 2 中编辑过,但我并不精通 jQuery。您可以自己添加更多 jQuery 等价物(社区维基答案)。 @Qantas94Heavy YouMightNotNeedjQuery 已经存在一段时间了,您可以参考它以获取更多信息。

以上是关于如果没有像 jQuery 这样的库,我如何操作 DOM? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

是否有一个轻量级的跨浏览器范围输入解决方案,不需要像 jQuery 这样的库

在 jQuery 中获取像我这样的所有元素?

TypeScript 和 jQuery 等库(带有 .d.ts 文件)

删除不需要的 jQuery 函数

如何在像犰狳这样的库中扩展一个类?

你没有看错,爬网页数据,C# 也可以像 Jquery 那样