直接使用id
如果元素有 id 属性,那么该 id 也会有一个同名全局变量; 如果声明了同名变量,则会被声明的变量覆盖
<div id="test">Test Element</div>
<div id="test-inner">Test Inner Element</div>
<div id="other">Test Element</div>
<script>
console.log(test)
console.log(window.test)
console.log(window['test-inner'])
let other = '掘金'
console.log(other)
</script>
在 规范 中描述了这种行为,浏览器尝试了混合 JS 和 DOM 的命名空间。但这仅对简单脚本有效,因为它们可能会产生命名冲突;而且当我们在 JS 中查看时,因为无法在视图中查看 HTML,所以变量的来源可能会很模糊;故此,建议不用这种方式获取元素。
document.getElementById('id')
强调三点:
-
getElementById 只能在
document对象上调用,它会在整个文档中查找给定的 id; -
getElementById 返回单个元素;
-
如果有多个元素具有同名 id,那么 getElementById 的行为将不可预测;浏览器将随机返回其他的一个;请严格遵守 id 的唯一性规则;
getElementsBy*
具体方法有:
elem.getElementsByTagName(tag)
- 适用于
任何节点; - tag 可以是具体的标签名,也可以是指代任何标签的 '*' ;
- 返回值是一个的
live集合(不是数组);
elem.getElementsByClassName(className)
- 适用于
任何节点; - 返回值是一个的
live集合(不是数组);
document.getElementsByName(name)
- 只适用于
document对象; - name 指的元素的 name 属性;
- 返回值是一个的
live集合(不是数组);
getElementsByName 示例:
<ul id="ul">
<li name="li">1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let ul = document.getElementById('ul')
let documentLi = document.getElementsByName('li')
console.log('documentLi:', documentLi)
let elemLi = ul.getElementsByName('li')
console.log('elemLi:', elemLi)
</script>
querySelector*
具体方法有:
elem.querySelectorAll(css)
- 适用于
任何节点; - css 指合法的 css选择器;
- 返回值是一个的
static集合(不是数组);
elem.querySelector(css)
- 适用于
任何节点; - css 指合法的 css选择器;
- 返回值是给定 CSS 选择器的第一个元素,等同于
elem.querySelectorAll(css)[0];
其它方法
elem.matches(css)
matches 不会查找任何内容,它检查 elem 是否匹配给定的 CSS 选择器,返回 true 或者 false。
elem.closest(css)
closest 会查找与 CSS 选择器匹配的最接近的祖先(elem 自己也会被搜索),返回单个元素
elemA.contains(elemB)
contains 用于检查父子关系,elemB 在 elemA中 或者当 elemA === elemB,返回 true
集合
到这,再来说说 live集合、static集合
live集合:反映文档的当前状态,它是实时的、动态的,即在文档变化时,集合的内容可以自动更新; getElementsBy* 均返回live集合。
static集合:则相反,它是不变的、固定的,即在文档变化时,集合的内容不会变化;querySelectorAll 返回static集合。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
// 分别调用 getBy 、 queryAll (只有获取li的方法不同)
getBy() // 分别输出 3 和 4
queryAll() // 分别输出 3 和 3
function getBy() {
const ul = document.getElementById('ul')
// 获取li
const lis = document.getElementsByTagName('li')
console.log(lis.length)
// 向ul中追加一个li
const newLi = document.createElement('li')
newLi.textContent = 'new li'
ul.appendChild(newLi)
console.log(lis.length)
}
function queryAll() {
const ul = document.getElementById('ul')
// 获取li
const lis = document.querySelectorAll('li')
console.log(lis.length)
// 向ul中追加一个li
const newLi = document.createElement('li')
newLi.textContent = 'new li'
ul.appendChild(newLi)
console.log(lis.length)
}
</script>
很容易看到不同之处:在文档中出现一个新的 li 后,live集合的元素会增加一个,static集合则不会增加。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
getBy()
function getBy() {
const ul = document.getElementById('ul')
const lis = document.getElementsByTagName('li')
for (let i = 0; i < lis.length; i++) {
const newLi = document.createElement('li')
newLi.textContent = i
ul.appendChild(newLi)
}
}
</script>
很明显 这个for循环,会是一个无限循环,因为当 i增加的时候, lis.length 也会增加。
总结
6 种主要的方法,可以在 DOM 中进行搜素
| 方法 | 匹配方式 | 适用对象 | 返回值 |
|---|---|---|---|
| getElementById | id | document | 单个元素 |
| getElementsByName | name | document | live集合 |
| getElementsByTagName | tag or '*' | anyNode | live集合 |
| getElementsByClassName | className | anyNode | live集合 |
| querySelectorAll | CSS-selector | anyNode | static集合 |
| querySelector | CSS-selector | anyNode | 单个元素 |