DOM操作之元素查找

发布时间 2023-12-26 12:36:44作者: 指尖,写不尽

通常我们操作一个元素节点前都需要查找到这个元素,查找到这个元素有两种方式。

  1. 使用选择器函数查找元素
  2. 通过元素的关系属性来查找元素

使用选择器函数查找

getElementById

通过节点元素的ID得到此节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>getElementById</title>
</head>
<body>
    <div id="box">id选择器</div>
    <div id="boxDiv">boxDiv</div>
    <div id="boxDiv">boxDiv</div>

    <script>
        var box = document.getElementById('box');
        var boxDiv = document.getElementById('boxDiv');
        console.log("box:", box);
        console.log("boxDiv:", boxDiv);
</script>
</body>
</html>

上面的例子中,id = ”boxDiv“ 有重复,在HTML的规则中, ID在一个网页应当是唯一的,如果重复, documen.getElementById 方法也只会获取第一个。

getElementsByName

通过名称获得节点, 返回的是一个数组集合

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="hidden" name="up" />
    <input type="hidden" name="down" />

    <script>
        const up_names = document.getElementsByName("up");
        console.log(up_names);
</script>
</body>
</html>

getElementByTagName

通过标签名得到一组标签数组

注意:此方法返回的是数组,即使页面上只有一个此节点的元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>getElementByTagName</title>
</head>
<body>
    <div>哈喽,第一</div>
    <div>哈喽,第二</div>
    <div>哈喽,第三</div>
    <div>哈喽,第四</div>

    <div id="divBox">
        <p>段落</p>
        <p>段落</p>
        <p>段落</p>
        <p>段落</p>
    </div>

    <script>
        // 得到一个div标签的数据
        var divS = document.getElementsByTagName('div');
        console.log(divS);

        var divBox = document.getElementById('divBox');
        var pArray = divBox.getElementsByTagName('p');
        console.log(pArray);
</script>
</body>
</html>

getElementByClassName

通过class选择器得到元素节点的数组

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>getElementByIdElementByClassName</title>
</head>
<body>

    <div id="box1">
        <p class="child box1Child">box1节点一</p>
        <p class="child box1Child">box1节点二</p>
        <p class="child box1Child">box1节点三</p>
        <p class="child box1Child">box1节点四</p>
    </div>
    <div id="box2">
        <p class="child box2Child">box2节点2</p>
        <p class="child box2Child">box2节点二</p>
        <p class="child box2Child">box2节点三</p>
        <p class="child box2Child">box2节点四</p>
    </div>
    <script>
        
        // 会获取到所有 包含 class = child 的元素
        var child = document.getElementsByClassName('child');
        console.log('child:',child);

        
        var box1 = document.getElementById('box1');
        
        // 获取 id 为 box1 下的所有 class = box2Child 的子元素
        var box1Children = box1.getElementsByClassName('box1Child');

        console.log('box1Children:',box1Children);
</script>
</body>
</html>

querySelector

通过选择器或者选择器组得到元素节点,只能得到页面上的一个元素,如果有多个元素符合条件,则只能得到第一个元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>querySelector</title>
</head>
<body>
    <div id="box1">
        <p>子元素</p>
        <p class="child">子元素1</p>
        <p class="child">子元素2</p>
    </div>

    <script>
        // querySelector 多个元素只会获得第一个
        var child = document.querySelector('#box1 .child');
        console.log('child:', child);
</script>
</body>
</html>

querySelectoryAll

通过选择器或者选择器组得到数组元素

注:返回值是一个数组

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>querySelector</title>
</head>
<body>
    <div id="box1">
        <p>子元素</p>
        <p class="child">子元素1</p>
        <p class="child">子元素2</p>
    </div>

    <script>
       
        // 根据元素选择器获取所有的子元素
        var children = document.querySelectorAll('#box1 .child');
        console.log('children:', children);
</script>
</body>
</html>
方法 功能
getElmentById 通过ID得到元素
getElementsByName 通过名称得到元素
getElementByTagName 通过标签名得到元素数组
getElementByClassName 通过类名得到元素数组
querySelector 通过选择器得到元素
querySelectoryAll 通过选择器得到元素数组

关系属性查找元素

关系属性查找,是根据已知的节点去查找我们想要的节点

节点和节点组成了一棵树,有以下几种角色

父节点:在一个嵌套结构中,外层的被成为内层节点的父节点

子节点:嵌套在父节点内部的节点

兄弟节点:处在同一层级,并列的节点被称为兄弟节点

<!--id为parentNode被称为父节点-->
<div id='parentNode'>
  <!--子节点-->
  <div></div>
  <div></div>
</div>
<!--parentNode2 和 parentNode 并列,称为兄弟节点 -->
<div id='parentNode2'>
<div>

这些角色之间有以下几种关系,我们就可以用这些关系属性获取相应的元素节点

关系 所有节点
子节点 childNodes
父节点 parentNode
第一个子节点 firstChild
最后一个子节点 lastChild
前一个兄弟节点 previousSibling
后一个兄弟节点 nextSlibling

拓展

DOM中,文本和空白也应该算DOM的节点, 所以用上述表格中的属性取的是所有的节点

在日常开发中,我们可能只需要操作元素节点(带标签的)的节点, 因此,有了以下属性方便我们操作

关系 元素节点
子节点 children
第一个子节点 firstElementChild
最后一个子节点 lastElementChild
前一个兄弟节点 previousElementSibling
后一个兄弟节点 nextElementSibling
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点关系</title>
</head>
<body>
    
    <div id="divBox">
        <p>文字文字</p>
        <p class="secondP">文字文字</p>
        <p>文字文字</p>
    </div>
    <script>
        var divBox = document.getElementById('divBox');

        // 打印所有子节点 (包含空文本等也算一个节点)
        console.log(divBox.childNodes);
        // 打印所有元素节点(从IE9开始兼容)
        console.log(divBox.children);

        
        // 打印父节点
        var secondP = document.querySelector('.secondP');
        console.log('secondP:', secondP.parentNode);

        // 第一个子节点
        var firstChild = divBox.firstChild;
        console.log('第一个子节点:', firstChild);

        // 第一个子元素节点
        var firstElementChild = divBox.firstElementChild;
        console.log('第一个子元素节点:', firstElementChild);

        // 最后一个子节点
        var lastChild = divBox.lastChild;
        console.log('最后一个子节点:', lastChild);

        // 最后一个元素节点
        var lastElementChild = divBox.lastElementChild;
        console.log('最后一个元素节点:', lastElementChild);

        // 前一个兄弟节点 如果没有返回null
        var previousSibling = secondP.previousSibling;
        console.log('前一个兄弟节点:', previousSibling);

        // 前一个兄弟元素节点, 如果没有返回null
        var previousElementSibling = secondP.previousElementSibling;
        console.log('前一个兄弟元素节点:', previousElementSibling);

        // 后一个兄弟节点, 如果没有返回null
        var nextSibling  = secondP.nextSibling;
        console.log('后一个兄弟节点:', nextSibling);

        // 后一个兄弟元素节点 , 如果没有返回null
        var nextElementSibling = secondP.nextElementSibling;
        console.log('后一个兄弟元素节点:', nextElementSibling);
</script>
</body>
</html>

上面获取元素节点的方法兼容到IE9, 其实我们可以使用前面文章中提到的 nodeType 来模拟实现 这些方法,这种写法可以兼容到IE6

我们知道 nodeType = 1 的为元素节点,因此我们通过方法模拟实现类似children属性的功能, 获取一个元素的所有子节点

以下为实现代码

<div id="divBox">
        <p>文字文字</p>
        <p class="secondP">文字文字</p>
        <p>文字文字</p>
    </div>
    <script>
        var divBox = document.getElementById('divBox');

        function getChildren(node) {
            // 结果数组
            var children = [];
            // 遍历node这个节点的所有子节点,判断每一个子节点的nodeType属性是不是1
            // 如果时1 , 就推入数组
            for(var i = 0 ; i < node.childNodes.length; i++) {
                if(node.childNodes[i].nodeType == 1) {
                    children.push(node.childNodes[i]);
                }
            }
            return children;
        }
        console.log(getChildren(divBox));
</script>