在开发现代网站时,大量使用用于DOM的JavaScript功能。 脚本允许您显示和隐藏从中构建页面的元素,配置这些元素的属性。 从程序进行交互的DOM对象具有属性和方法。 根据该材料的作者所说,几乎所有的Web程序员都知道其中一些内容,我们今天出版的是其翻译版本。 但是他想在这里谈论的一些远不那么著名。

HTML和DOM
首先,让我们谈谈HTML和DOM之间的区别。 例如,常规的
<table<
元素显然是HTML代码。 该元素可以在html文件中使用;它具有一组属性,这些属性确定在其帮助下创建的表的外观和行为。 严格来说,
<table>
标记本身与JavaScript无关。 文档中存在的HTML元素与JavaScript代码之间的关系由DOM(文档对象模型)提供。 DOM使与JavaScript代码中的HTML元素进行交互成为可能,就好像它们是对象一样。
所有HTML元素都有自己的“ DOM接口”,用于定义属性(它们通常与HTML元素的属性相关联)和方法。 例如,
<table>
元素具有一个称为
HTMLTableElement的接口。
例如,可以使用以下构造获取到元素的链接:
const searchBox = document.getElementById('search-box');
接收到元素的链接后,程序员可以访问此类元素具有的属性和方法。 例如,您可以使用某个文本字段的
value
属性,假设使用该文本字段的链接使用
searchBox.value
形式的结构存储在
searchBox
变量中。 您可以通过调用光标的
searchBox.focus()
方法将其放置在此文本字段中。
也许这是我们可以完成“关于DOM的简短课程”的地方,实际上,可以进入鲜为人知的HTML元素DOM接口的属性和方法。
如果您想立即阅读和试验,请打开浏览器开发人员工具。 特别是,为了获得指向某个页面元素的链接,可以在元素树中选择它,然后在
控制台中使用
$0
构造。 要将项目作为对象查看,请在控制台中键入
dir($0)
。 顺便说一句,如果您偶然发现了一些新东西,请尝试使用控制台进行探索。
第1种:表格方法
适度的
<table>
元素(在网页布局开发中所使用的技术中仍居首位)具有相当多的非常好的方法,这些方法极大地简化了构建表的过程。
这里有一些。
const tableEl = document.querySelector('table'); const headerRow = tableEl.createTHead().insertRow(); headerRow.insertCell().textContent = 'Make'; headerRow.insertCell().textContent = 'Model'; headerRow.insertCell().textContent = 'Color'; const newRow = tableEl.insertRow(); newRow.insertCell().textContent = 'Yes'; newRow.insertCell().textContent = 'No'; newRow.insertCell().textContent = 'Thank you';
如您所见,这里我们不使用诸如
document.createElement()
类的命令。 如果直接在表上调用
.insertRow()
方法,它甚至还会提供
<tbody>
的附加内容。 这不是很好吗?
#2:scrollIntoView()方法
您可能知道,如果链接具有
#something
类的
#something
,那么在加载页面后,浏览器将自动滚动到具有相应
ID
的元素? 该方法很方便,但是如果在页面加载后呈现了我们感兴趣的元素,它将无法正常工作。 这是您自己重新创建此行为模式的方法:
document.querySelector(document.location.hash).scrollIntoView();
第三名:隐藏财产
在这里,我们考虑一个属性,但是最有可能在访问该属性时,将调用某个设置程序,这是一种方法。 无论如何,请记住,您是否曾经使用以下所示的设计来隐藏元素?
myElement.style.display = 'none'
如果您使用它,就不要再这样做了。 要隐藏元素,只需将
true
写入其
hidden
属性:
myElement.hidden = true
#4:toggle()方法
实际上,这不是某种方法。 这是元素属性方法。 特别是,此方法允许您使用以下构造将类添加到元素并将其从元素中删除:
myElement.classList.toggle('some-class')
顺便说一句,如果您曾经使用
if
构造添加过类,请注意,您不必再执行此操作,而无需考虑此构造。 使用
toggle()
方法的第二个参数可以实现相同的机制。 如果这是一个表达式,其结果为
true
,则传递给
toggle()
的类将添加到该元素。
el.classList.toggle('some-orange-class', theme === 'orange');
可能在这里,您可能对该设计的适当性有疑问。 毕竟,该方法的名称“ toggle”(考虑到该方法所执行的动作的本质已隐藏在其中)可以翻译为“ switch”,但没有提及“ switching”表示满足特定条件。 但是,尽管Internet Explorer的开发人员可能也认为它很奇怪,但上述设计仍以这种形式存在。 在实现
toggle()
未提供第二个参数。 因此,尽管上面已经说过,知道
toggle()
可以忘记
if
构造,但是不要忘记它。
#5:querySelector()方法
您肯定已经知道此方法的存在,但是有一种怀疑是,您中有17%的人不知道该方法可用于任何元素。
例如,构造
myElement.querySelector('.my-class')
仅选择具有
my-class
并且同时是
myElement
元素的后代的
myElement
元素。
#6:最接近()方法
所有支持父元素搜索的元素都具有此方法。 这类似于
querySelector()
的反向操作。 例如,使用此方法,您可以获得当前部分的标题:
myElement.closest('article').querySelector('h1');
在此,在搜索过程中,首先检测到第一个父元素
<article>
,然后检测到第一个父元素
<h1>
。
#7:getBoundingClientRect()方法
getBoundingClientRect()
方法返回一个装饰精美的小对象,其中包含有关调用此方法的元素的大小的信息。
{ x: 604.875, y: 1312, width: 701.625, height: 31, top: 1312, right: 1306.5, bottom: 1343, left: 604.875 }
但是,使用此方法时必须特别注意两点:
- 调用此方法将导致页面重绘。 根据查看页面的设备以及页面的复杂程度,此操作可能需要几毫秒的时间。 如果您打算在某些重复的代码段中调用此方法,请考虑这一点,例如在执行动画时。
- 并非所有浏览器都支持此方法。
#8:matches()方法
假设我们需要检查某个元素是否具有某个类。
显然,这是最困难的解决方法:
if (myElement.className.indexOf('some-class') > -1) {
这是另一种选择,它更好,但也远非理想:
if (myElement.className.includes('some-class')) {
这是解决此问题的最佳方法:
if (myElement.matches('.some-class')) {
#9:insertAdjacentElement()方法
此方法类似于
appendChild()
,但是在将子元素添加到何处的过程中具有更多功能。
因此,
parentEl.insertAdjacentElement('beforeend', newEl)
命令类似于
parentEl.appendChild(newEl)
,但是使用
insertAdjacentElement()
方法,您可以将
beforebegin
,
afterbegin
和
afterend
,指示需要放置的位置添加项目。
第10条:contains()方法
您是否曾经想知道一个元素是否在另一个元素内部? 我一直都需要。 例如,如果在处理鼠标单击事件时需要确定它是在模态窗口内还是在模态窗口外(这意味着可以将其关闭),则可以使用以下构造:
const handleClick = e => { if (!modalEl.contains(e.target)) modalEl.hidden = true; };
此处,
modalEl
是到模式窗口的链接,而
e.target
是单击的任何元素。 有趣的是,当我使用这种技术时,即使我记得自己经常犯错误并尝试提前修复可能的错误,也永远都不会第一次就正确地编写所有内容。
#11:getAttribute()方法
也许可以将这种方法称为最无用的方法,但是在某些情况下,它肯定可以派上用场。
还记得我们之前说过的DOM对象的属性通常与HTML元素的属性相关联吗?
情况并非如此的情况之一由
href
属性表示,例如,例如:
<a href="/animals/cat">Cat</a>
。
如您所料,
el.href
构造
el.href
不返回
/animals/cat
。 这是因为
<a>
元素实现了
HTMLHyperlinkElementUtils接口,该接口具有许多帮助程序属性,例如
protocol
和
hash
,可以帮助您弄清链接的详细信息。
这些帮助程序属性之一是
href
属性,它提供了完整的URL,其中包括相对URL在属性中不包含的所有内容。
结果,为了准确获取
href
属性中编写的内容,您需要使用
el.getAttribute('href')
构造。
第12条:<dialog>元素的三种方法
相对较新的
<dialog>
元素具有两个有用的但很普通的方法,而一个可以简单地称为美妙的方法。 因此,
show()
和
close()
方法完全可以实现您对它们的期望,显示和隐藏窗口。 我们称它们有用,但很普通。 但是
showModal()
方法将在其他所有内容的顶部显示
<dialog>
元素,并将其显示在窗口的中央。 事实上,通常希望从模态窗口中获得这种行为。 使用此类元素时,无需考虑
z-index
属性,手动添加模糊的背景或侦听按下
Escape
键以关闭相应窗口的事件。 浏览器知道模态窗口应如何工作,并确保一切正常运行。
#13:forEach()方法
有时,当您获得到元素列表的链接时,可以使用
forEach()
方法
forEach()
这些元素。
for()
循环是昨天。 假设我们需要在日志页面中列出所有
<a>
元素。 如果我们如下所示执行此操作,则会遇到错误消息:
document.getElementsByTagName('a').forEach(el => { console.log(el.href); });
为了解决此问题,可以使用以下构造:
document.querySelectorAll('a').forEach(el => { console.log(el.href); });
这里的要点是,诸如
getElementsByTagName()
之类的方法返回
HTMLCollection
类型的对象,而
querySelectorAll
对象。 通过
NodeList
对象的接口,我们可以访问
forEach()
方法(以及
keys()
,
values()
和
entries()
方法)。
实际上,如果这样的方法仅返回普通数组,而没有为我们提供某些看上去有用的方法,而这些方法却不太像数组,那会更好。 但是,不要因此而烦恼,因为ECMA的聪明人为我们提供了一个很棒的方法
Array.from()
,它使我们能够将所有看起来像数组的东西变成数组。
结果,您可以编写以下内容:
Array.from(document.getElementsByTagName('a')).forEach(el => { console.log(el.href); });
这是一件好事。 通过将原来的数组转换成数组,我们有机会使用许多数组方法,例如
map()
,
filter()
和
reduce()
。 例如,在这里,如何在页面上形成外部链接数组:
Array.from(document.querySelectorAll('a')) .map(el => el.origin) .filter(origin => origin !== document.origin) .filter(Boolean);
顺便说一句,我真的很喜欢
.filter(Boolean)
构造,因为当我很久以前在代码中遇到它时,我几乎无法立即理解它的含义。
第14号:使用表格
您很可能会知道
<form>
元素具有一个
submit()
方法。 但是,您不太可能知道表单具有
reset()
方法,并且它们具有
reportValidity()
方法,该方法适用于使用验证表单元素的情况。
此外,在使用表单时,您可以使用它们的
elements
属性,该属性通过一点允许您使用其
name
属性访问表单元素。 例如,
myFormEl.elements.email
构造将返回属于以下形式的
<input name="email" />
元素(“属于”不一定表示“成为后代”)。
这里应该注意,
elements
属性本身不返回普通元素的列表。 它返回控件列表(当然,该列表不是数组)。
这是一个例子。 如果表单上有三个单选按钮,并且它们都具有相同的名称(
animal
),则
formEl.elements.animal
构造将提供指向一组单选按钮(1个控件,3个HTML元素)的链接。 并且,如果您使用设计
formEl.elements.animal.value
,那么它将提供用户选择的单选按钮的值。
如果您考虑一下,那么一切看起来都很奇怪,因此让我们处理前面的示例:
#15:select()方法
也许在材料的最后,最好谈论一些绝对令人惊讶的方法,尽管这种方法可能对某人是一个启示。 因此,
.select()
方法使您可以在被调用的输入字段中选择文本。
总结
在本文中,我们讨论了可用于处理网页内容的鲜为人知的方法和属性。 我们希望您在这里为自己找到了一些新的东西,也许不仅是新的,而且是有用的。
亲爱的读者们! 您是否使用任何与尚不为人所知的网页内容进行程序交互的方式?
