在上一节中,我们学习了DOM树和遍历DOM相关的知识。可以通过firstChild
(或firstElementChild
)、lastChild
(或lastElementChild
)、parentNode
(或parentElement
)、children
、previousSibling
(或previousElementSibling
)、nextSibling
(或nextElementSibling
)获取到你想要的DOM元素。如果你够仔细的话,可以看到他们之前都是存在相互关系的,要么是兄弟关系,要么是父子关系。比如下图,更易于帮助大家理解:
当元素彼此接近时,我们使用上面所说的DOM属性可以很容易找到你想要的元素(DOM节点)。但事实上,很多时候并不是这样(他们不是有相互的关系)。此时如何获得页面的任意元素,也是JavaScript中的重要技能之一。那么除上一节所介绍的方法之外,还有别的方法吗?
答案肯定是有的,也就是我们今天要聊的getElement*
和querySelector*
:
getElementById()
getElementsByClassName()
getElementsByTagName()
getElementsByName()
document.querySelector()
document.querySelectorAll()
那我们开始吧!
document.getElementById
或者只是id
在HTML文档中,元素的id
是唯一的,也就是说,一个页面只有唯一的id
名,这个id
就是一个全局变量(如果应用到JavaScript中的话)。那么我们就可以用它来访问元素,比如像下面这样:
上面输出的结果如下:
如果我们自己显式声明一个相同的变量,那么输出的值就不一样了,比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let elem = 5;
console.log(elem) // => 5
</pre>
这个时候输出的值是5
,不再是<div id="elem"></div>
。
该行为在规范中已有相应的描述。浏览器试图通过混合JavaScript和DOM来帮助我们。对于简单的JavaScript脚本是有一定的好处的,但可能有名称冲突。同样,当我们查看JavaScript和没有HTML的时候,不知道变量是从哪来的。
更好的选择方法是使用document.getElementById(id)
。比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let elem = document.getElementById('elem')
elem.style.backgroundColor = 'red'
</pre>
在JavaScript中,我们经常使用id
来直接引用一个元素(选中元素),这是最为简单而且直接的方法。事实上,document.getElementById
是首选的方法。
需要注意的是,id
是唯一的,按规范的原则性来说,id
也必须是唯一的。言外之意,文档中只有一个元素与给定的id
相匹配。如果当文档中有多个具有相同id
的元素时,那么相应的方法document.getElementById()
获取的元素行为是不可预测的。浏览器可能会随机返回任何一个。所以,我们在使用的时候,必须保持id
的独特性,唯一性。
document.getElementById()
只能在document
对象上调用,它在整个文档中查找给定的id
。
其实,在JavaScript中,我们可以使用document.querySelector(id)
来获取指定的id
的元素。这个稍后我们会介绍到。
document.getElementsBy*
在JavaScript中,还有其他寻找节点的方法,比如:
document.getElementsByTagName(tag)
document.getElementsByClassName(className)
document.getElementsByName(name)
上面三个方法对应的是通过元素的标签名、类名和属性来获取想要的元素节点。
document.getElementsByTagName(tag)
查找带有给定标签的元素,将返回的是一个集合。tag
参数可以是任何HTML的标签元素,甚至也可以是*
。比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let divs = document.getElementsByTagName('div')
</pre>
这个方法在任何DOM元素的上下文中都可以调用的。比如ele.getElementsByTagName('div')
。比如前面的示例中,divs
获取到的是整个HTML文档中的所有div
标签元素,其输出的值是一个HTMLCollection
集合,如下图所示:
比如下面的这个示例,我们要找到table
中的所有input
标签,我们可以这样做:
这个输出的结果如下:
对于getElementsBy*
等方法,千万别忘了s
字母,特别是新手。也就是说,当你使用getElementByTagName
等方法将会报错。
getElementById
中缺少一个s
字母,因为它返回的是单个元素。但是getElementsByTagName
返回的是一个集合,所以里面有一个s
。同样的,getElementsByClassName
和getElementsByName
与getElementsByTagName
类似。
还有就是,getElementsBy*
等方法返回的是一个集合,而不是一个元素(与getElementById
不同)。同样的,很多新手还容易犯另外一个书写错误:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
document.getElementsByTagName('input').value = 5
</pre>
虽然上面的代码并不报错,但是并不会修改HTML元素中input
的value
值,如下图所示:
这主要是因为,document.getElementsByTagName('input')
返回的不是一个独立的元素,而是一个集合。其实它返回的就是一个HTMLCollection
集合。如果你阅读过这个系列的前两篇文章,你就不难发现,返回的值是一个类数组。返回值具有length
属性和[]
和item()
相关的特性。如果想改变所有input
的value
值,可以使用for ... of
这样的方法。当然,如果你想获取指定的某个input
的值,我们可以使用指定的索引值,比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
document.getElementsByTagName('input')[0].value = 5 document.getElementsByTagName('input')[1].value = '大漠' document.getElementsByTagName('input')[2].value = '大漠_w3cplus'
</pre>
其中:
document.getElementsByClassName(className)
返回具有给定CSS类的元素,元素可能还有其他的类document.getElementsByName(name)
返回具有给定name
属性的元素。不过由天历史原因,这个方法很少使用
动态集合
所有方法getElementsBy*
返回的是一个动态集合。这样的集合总是反映文档的当前状态,并在更改时自动更新。
在下面的示例中,有两个<script>
。
第一个
script
中创建了<div>
的集合。它的length
是1
第二个
script
运行之后,浏览器会再遇到一个<div>
,所以它的length
是2
比如:
在JavaScript中,除了document.getElementsBy*
可以获取元素之外,还可以通过document.querySelector*
来获取。比如上面的示例,如果我们换成:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let divs = document.querySelectorAll('div')
</pre>
console.log(divs)
返回的是一个静态集合。它就像一个固定的元素数组。其divs.length
的值是1
。就算是像上面的示例,在两个script
中,其输出的也是1
。
document.querySelector*
接下来,咱们来看querySelector()
和querySelectorAll()
方法怎么来获取想要的DOM元素。比如下面这样的一个示例:
在这个示例中,div#main
包含了4
个div
,同时第个div
包含一个img
元素。它们分别具有pictureContainer
和theimage
类名。接下来的内容将围绕这个示例,使用querySelector()
和querySelectorAll()
方法将会发生什么。
querySelector()
函数的基本工作如下:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
var element = document.querySelector('<CSS Selector>')
</pre>
querySelector()
函数接受一个参数,这个参数是你要查找的元素的CSS选择器。在JavaScript中,document.querySelector()
返回的内容始终找到的是HTML中指定的第一个元素。
比如上面的HTML示例,如果我们想要访问id
为main
的div
,使用document.querySelector()
方法获得:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let element = document.querySelector('#main')
</pre>
因为main
是一个id
,所以针对它的选择器语法将是#main
。同样的,如果你要根据指定的类名来选择元素,也是可以的,比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let element = document.querySelector('.pictureContainer')
</pre>
返回的是第一个类名为pictureContainer
的div
。其他类名为pictureContainer
的div
元素将会被忽略。
回到这里,使用document.getElementById()
和document.querySelector('id')
选择到的元素是相同的。
document.querySelectorAll()
函数返回所有元素,它找到匹配你提供的任何选择器:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let elements = document.querySelectorAll("< CSS selector >");
</pre>
除了返回的元素数量之外,所描述的关于querySelector()
所有的内容都适用querySelectorAll()
。不过,两者不同的是,querySelectorAll()
返回的不是单个元素,而返回的是一个数组(不过也是一个类数组)。
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let imgWrap = document.querySelector('.pictureContainer')
let imgWraps = document.querySelectorAll('.pictureContainer')
</pre>
[图片上传失败...(image-7f53dc-1527513843136)]
querySelector()
和querySelectorAll()
函数时,里面的参数可以使用CSS选择器的所有方法。
咱们小结一下。在DOM中获取元素(或节点)有六种常用的方法:
注意,
getElementById()
和getElementsByName()
只能在document
上下调用。document.getElementById(...)
可用,但不能elem.getElementById(...)
,这将会导致错误。
其他方法可以用在元素上,比如,elem.querySelectorAll()
,可以在指定的elem
元素中搜索指定的选择器。除此之外:
elem.matches(css)
用来检查elem
是否匹配指定的css
选择器elem.closest(css)
用来查找匹配给定的CSS选择器的最近的祖先elemA.contains(elemB)
表示的是如果elemB
是否包含elemA
,如果包含就返回true
总结
这篇文章主要介绍了DOM中获取元素(或节点)的方法getElement*
和 querySelector*
,其主要包括:
getElementsByTagName()
getElementsByName()
getElementsByClassName()
getElementById()
querySelector()
querySelectorAll()
综合上一节的内容,在DOM中选择所要匹配的方法和属性,其实也对应的DOM中查、改、增、删中的查:
当然,具体的使用方法应该根据自己的需求来选择。没有更好的,只有合适的。