DOM系列:getElement* 和 querySelector*

在上一节中,我们学习了DOM树和遍历DOM相关的知识。可以通过firstChild(或firstElementChild)、lastChild(或lastElementChild)、parentNode(或parentElement)、childrenpreviousSibling(或previousElementSibling)、nextSibling(或nextElementSibling)获取到你想要的DOM元素。如果你够仔细的话,可以看到他们之前都是存在相互关系的,要么是兄弟关系,要么是父子关系。比如下图,更易于帮助大家理解:

image

当元素彼此接近时,我们使用上面所说的DOM属性可以很容易找到你想要的元素(DOM节点)。但事实上,很多时候并不是这样(他们不是有相互的关系)。此时如何获得页面的任意元素,也是JavaScript中的重要技能之一。那么除上一节所介绍的方法之外,还有别的方法吗?

答案肯定是有的,也就是我们今天要聊的getElement*querySelector*

  • getElementById()

  • getElementsByClassName()

  • getElementsByTagName()

  • getElementsByName()

  • document.querySelector()

  • document.querySelectorAll()

那我们开始吧!

document.getElementById或者只是id

在HTML文档中,元素的id是唯一的,也就是说,一个页面只有唯一的id名,这个id就是一个全局变量(如果应用到JavaScript中的话)。那么我们就可以用它来访问元素,比如像下面这样:

image

上面输出的结果如下:

image

如果我们自己显式声明一个相同的变量,那么输出的值就不一样了,比如:

<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集合,如下图所示:

image

比如下面的这个示例,我们要找到table中的所有input标签,我们可以这样做:

image

这个输出的结果如下:

image

对于getElementsBy*等方法,千万别忘了s字母,特别是新手。也就是说,当你使用getElementByTagName等方法将会报错。

image

getElementById中缺少一个s字母,因为它返回的是单个元素。但是getElementsByTagName返回的是一个集合,所以里面有一个s。同样的,getElementsByClassNamegetElementsByNamegetElementsByTagName类似。

还有就是,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元素中inputvalue值,如下图所示:

image

这主要是因为,document.getElementsByTagName('input')返回的不是一个独立的元素,而是一个集合。其实它返回的就是一个HTMLCollection集合。如果你阅读过这个系列的前两篇文章,你就不难发现,返回的值是一个类数组。返回值具有length属性和[]item()相关的特性。如果想改变所有inputvalue值,可以使用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>

image

其中:

  • document.getElementsByClassName(className)返回具有给定CSS类的元素,元素可能还有其他的类

  • document.getElementsByName(name)返回具有给定name属性的元素。不过由天历史原因,这个方法很少使用

动态集合

所有方法getElementsBy*返回的是一个动态集合。这样的集合总是反映文档的当前状态,并在更改时自动更新。

在下面的示例中,有两个<script>

  • 第一个script中创建了<div>的集合。它的length1

  • 第二个script运行之后,浏览器会再遇到一个<div>,所以它的length2

比如:

image

在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元素。比如下面这样的一个示例:

image

在这个示例中,div#main包含了4div,同时第个div包含一个img元素。它们分别具有pictureContainertheimage类名。接下来的内容将围绕这个示例,使用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示例,如果我们想要访问idmaindiv,使用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>

返回的是第一个类名为pictureContainerdiv。其他类名为pictureContainerdiv元素将会被忽略。

image

回到这里,使用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中获取元素(或节点)有六种常用的方法:

image

注意,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中查、改、增、删中的

image

当然,具体的使用方法应该根据自己的需求来选择。没有更好的,只有合适的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341

推荐阅读更多精彩内容

  • 第一章 1.什么是DOM DOM: Document Object Model(文档对象模型) 是JavaScri...
    fastwe阅读 786评论 0 0
  • 题目1: dom对象的innerText和innerHTML有什么区别? innerText是一个可写属性,返回元...
    Taaaaaaaurus阅读 199评论 0 1
  • 问答 一、dom对象的innerText和innerHTML有什么区别? innerTextinnerText是一...
    婷楼沐熙阅读 397评论 0 0
  • 题目1: dom对象的innerText和innerHTML有什么区别? innerText是一个可写属性,返回元...
    QQQQQCY阅读 181评论 0 0
  • 欢迎关注个人微信公众账号:byodian个人博客:Byodian's Blog JavaScript 基础知识总结...
    工具速递阅读 749评论 0 3