思悟博客
  • 首页
  • 分类
    • 随笔
    • WEB开发
    • 软件及系统
    • 杂类
  • 关于本站
  • 友情链接
    • Dxoca's blog
    • Noahの梦想
爱好、实践、创新
  1. 首页
  2. 开发
  3. HTML、CSS、JS
  4. 正文

DOM系列:getElement* 和 querySelector*

2018年05月25日 1071点热度 0人点赞 0条评论

在上一节中,我们学习了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中的话)。那么我们就可以用它来访问元素,比如像下面这样:

<div id="elem">
    <div id="elem-content">Element</div>
</div>

<script>
    console.log(elem)   // => 带有id="elem"的DOM-element
    console.log(window.elem) // => 访问全局变量也是有效的
    // 对于`elem-content`来说,它更复杂一些,里面有一个破折号,所以它不能是一个变量名
    // 但是可以使用方括号[]
    console.log(window['elem-content'])
</script>

上面输出的结果如下:

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

let elem = 5;
console.log(elem) // => 5

这个时候输出的值是5,不再是<div id="elem"></div>。

该行为在规范中已有相应的描述。浏览器试图通过混合JavaScript和DOM来帮助我们。对于简单的JavaScript脚本是有一定的好处的,但可能有名称冲突。同样,当我们查看JavaScript和没有HTML的时候,不知道变量是从哪来的。

更好的选择方法是使用document.getElementById(id)。比如:

let elem = document.getElementById('elem')
elem.style.backgroundColor = 'red'

在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的标签元素,甚至也可以是*。比如:

let divs = document.getElementsByTagName('div')

这个方法在任何DOM元素的上下文中都可以调用的。比如ele.getElementsByTagName('div')。比如前面的示例中,divs获取到的是整个HTML文档中的所有div标签元素,其输出的值是一个HTMLCollection集合,如下图所示:

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

<table id="table">
    <tr>
        <td>Your age:</td>
        <td>
            <label>
                <input type="radio" name="age" value="young" checked> less than 18
            </label>
            <label>
                <input type="radio" name="age" value="mature"> from 18 to 50
            </label>
            <label>
                <input type="radio" name="age" value="senior"> more than 60
            </label>
        </td>
    </tr>
</table>

<script>
    let table = document.getElementById('table')
    let inputs = table.getElementsByTagName('input')

    console.log(inputs)

    for (let input of inputs ) {
        console.log(`${input.value}: ${input.checked}`)
    }
</script>

这个输出的结果如下:

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

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

还有就是,getElementsBy*等方法返回的是一个集合,而不是一个元素(与getElementById不同)。同样的,很多新手还容易犯另外一个书写错误:

document.getElementsByTagName('input').value = 5

虽然上面的代码并不报错,但是并不会修改HTML元素中input的value值,如下图所示:

这主要是因为,document.getElementsByTagName('input')返回的不是一个独立的元素,而是一个集合。其实它返回的就是一个HTMLCollection集合。如果你阅读过这个系列的前两篇文章,你就不难发现,返回的值是一个类数组。返回值具有length属性和[]和item()相关的特性。如果想改变所有input的value值,可以使用for ... of这样的方法。当然,如果你想获取指定的某个input的值,我们可以使用指定的索引值,比如:

document.getElementsByTagName('input')[0].value = 5
document.getElementsByTagName('input')[1].value = '大漠'
document.getElementsByTagName('input')[2].value = '大漠_w3cplus'

其中:

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

动态集合

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

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

  • 第一个script中创建了<div>的集合。它的length是1
  • 第二个script运行之后,浏览器会再遇到一个<div>,所以它的length是2

比如:

<div>First div</div>
<script>
    let divs = document.getElementsByTagName('div')
    console.log(divs.length) // => 1
</script>

<div>Second div</div>
<script>
    console.log(div.length) // => 2
</script>

在JavaScript中,除了document.getElementsBy*可以获取元素之外,还可以通过document.querySelector*来获取。比如上面的示例,如果我们换成:

let divs = document.querySelectorAll('div')

console.log(divs)返回的是一个静态集合。它就像一个固定的元素数组。其divs.length的值是1。就算是像上面的示例,在两个script中,其输出的也是1。

document.querySelector*

接下来,咱们来看querySelector()和querySelectorAll()方法怎么来获取想要的DOM元素。比如下面这样的一个示例:

<div id="main">
    <div class="pictureContainer">
        <img class="theimage" src="smiley.png" height="300" width="150"/>
    </div>
    <div class="pictureContainer">
        <img class="theimage" src="tongue.png" height="300" width="150"/>
    </div>
    <div class="pictureContainer">
        <img class="theimage" src="meh.png" height="300" width="150"/>
    </div>
    <div class="pictureContainer">
        <img class="theimage" src="sad.png" height="300" width="150"/>
    </div>
</div>

在这个示例中,div#main包含了4个div,同时第个div包含一个img元素。它们分别具有pictureContainer和theimage类名。接下来的内容将围绕这个示例,使用querySelector()和querySelectorAll()方法将会发生什么。

querySelector()函数的基本工作如下:

var element = document.querySelector('<CSS Selector>')

querySelector()函数接受一个参数,这个参数是你要查找的元素的CSS选择器。在JavaScript中,document.querySelector()返回的内容始终找到的是HTML中指定的第一个元素。

比如上面的HTML示例,如果我们想要访问id为main的div,使用document.querySelector()方法获得:

let element = document.querySelector('#main')

因为main是一个id,所以针对它的选择器语法将是#main。同样的,如果你要根据指定的类名来选择元素,也是可以的,比如:

let element = document.querySelector('.pictureContainer')

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

回到这里,使用document.getElementById()和document.querySelector('id')选择到的元素是相同的。

document.querySelectorAll()函数返回所有元素,它找到匹配你提供的任何选择器:

let elements = document.querySelectorAll("< CSS selector >");

除了返回的元素数量之外,所描述的关于querySelector()所有的内容都适用querySelectorAll()。不过,两者不同的是,querySelectorAll()返回的不是单个元素,而返回的是一个数组(不过也是一个类数组)。

let imgWrap = document.querySelector('.pictureContainer')
let imgWraps = document.querySelectorAll('.pictureContainer')

querySelector()和querySelectorAll()函数时,里面的参数可以使用CSS选择器的所有方法。

咱们小结一下。在DOM中获取元素(或节点)有六种常用的方法:

方法 参数 是否调用一个元素? 是动态?
document.getElementById() id
document.getElementsByName() name ✔
document.getElementsByTagName() tag 或 * ✔ ✔
document.getElementsByClassName() class ✔ ✔
document.querySelector() CSS Selector ✔
document.querySelectorAll() CSS Selector ✔

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

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

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.w3cplus.com/javascript/searching-elements-dom.html

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.w3cplus.com/javascript/searching-elements-dom.html © w3cplus.com

标签: 暂无
最后更新:2018年05月25日
chao

chao

保持求知的状态,每天一点小进步。

点赞
< 上一篇
下一篇 >

期待你的神评呦~

avatar
This comment form is under antispam protection
avatar
This comment form is under antispam protection
  订阅  
提醒
用户您好!请先登录!
登录 注册
标签聚合
js 对象 PHP 教程 object this 代理 Linux
最新 热点 随机
最新 热点 随机
群晖 GitServer用户为空的解决办法 压缩包处理软件Bandizip破解版下载 宝塔面板安装PHP-Memcached插件失败解决办法 Bing 图片API AdGuard-轻量级的全平台广告过滤工具 Microsoft Wi-Fi Direct Virtual关闭方法 双显卡OBS无图像解决办法(包含集显运行依旧无图像办法) 免费游戏加速器推荐--蓝泡
DOM系列:DOM树和遍历DOM 前端基础-jQuery的优点以及用法 30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度) 前端基础进阶(十四):es6常用基础合集 Bing 图片API 世界,您好! SSTap:简单快速的全局代理(游戏加速) Chrome 控制台新玩法-console显示图片以及为文字加样式
下面内容为广告
2020年一月
一 二 三 四 五 六 日
 1234
567891011
12131415161718
19202122232425
262728293031  
« 12月    

COPYRIGHT © 2020 思悟博客. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

wpDiscuz
登录
注册|忘记密码?