JS DOM 编程复习笔记--父元素、子元素和兄弟元素(三)

727 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

今天我们来复习DOM中的获取父元素、子元素和兄弟元素的API,它们主要有parentNodefirstChildfirstElementChildlastChildlastElementChildchildNodeschildrennextElementSiblingnextSiblingpreviousElementSiblingpreviousSibling等。

目录

  • 获取父元素 - parentNode

  • 获取子元素 -firstChildfirstElementChildlastChildlastElementChildchildNodeschildren

  • 获取兄弟元素 - nextElementSiblingnextSiblingpreviousElementSiblingpreviousSibling

获取父元素

parentNode 属性

获取DOM树中指定节点的父节点,我们可以使用parentNode 属性

let parent = node.parentNode;

parentNode 为只读属性

DocumentDocumentFragment 没有父节点,所以 parentNode 属性将会为 null

parentNode 例子

下面是一个简单的页面

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript parentNode</title>
</head>
<body>
  <div id="main">
    <p class="note">这是一个段落</p>
  </div>

  <script>
    let note = document.querySelector('.note');
    console.log(note.parentNode);
  </script>
</body>
</html>

控制台打印结果

image-20211019150342852

如果没有指定的元素没有父元素 parentNode 属性也会为 null

获取子元素

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Child Elements</title>
</head>
<body>
  <ul id="menu">
    <li class="first">首页</li>
    <li>产品</li>
    <li class="current">新闻</li>
    <li>博客</li>
    <li>投资者</li>
    <li>文档</li>
    <li class="last">关于我们</li>
  </ul>
</body>
</html>

firstChild

获取指定元素的第一个子节点,使用 firstChild 属性

let firstChild = parentElement.firstChild; 

如果父元素没有任何子元素,则firstChild 返回null。firstChild 属性返回一个子节点,它可以是任何节点类型,例如元素节点、文本节点或注释节点。

let content = document.getElementById('menu');
let firstChild = content.firstChild.nodeName;
console.log(firstChild);

// 输出:
// #text

上面的代码输出#text,而不是li节点,这是因为ulli之间有一段空白。

在HTML中任何空格(单个空格、多个空格、回车符和制表符)都将创建一个 #text 节点。 要删除 #text 节点,可以删除空格,如下所示

<ul id="menu"><li class="first">首页</li><li>产品</li></ul>

如果我要获取第一个元素类型的子节点,我们可以使用firstElementChild属性

let firstElementChild = parentElement.firstElementChild;

下面代码将输出第一个li元素

let content = document.getElementById('menu');
console.log(content.firstElementChild);

// 输出:
// <li class="first">首页</li>

lastChild

同理要获取节点的最后一个子节点,我们使用 lastChild 属性

let lastChild = parentElement.lastChild;

firstChild一样,如果想获取最后一个子元素,使用lastElementChild 属性

let lastChild = parentElement.lastElementChild;

下面代码将会返回ui最后一个li元素

let menu = document.getElementById('menu');
console.log(menu.lastElementChild);

// 输出:
// <li class="last">关于我们</li>

childNodes

获取指定元素的子元素NodeList,使用childNodes属性

let children = parentElement.childNodes;

firstChildlastChild相似

childNodes 属性返回具有任何节点类型的所有子元素。 要仅获取元素节点类型的子元素,请使用 children 属性:

let children = parentElement.children;

下面代码将获取ul下的所有子元素

let menu = document.getElementById('menu');
let children = menu.children;
console.log(children);

输出如下图

image-20211019152812056

兄弟元素

如何获取一个元素的下一个兄弟元素、前一个兄弟元素和所有兄弟元素,假如我们的HTML结构如下

<ul id="menu">
  <li>首页</li>
  <li>产品</li>
  <li class="current">新闻</li>
  <li>博客</li>
  <li>投资者</li>
  <li>文档</li>
  <li>关于我们</li>
</ul>

下一个兄弟元素

要获取下一个兄弟元素,使用 nextElementSibling 属性

let nextSibling = currentNode.nextElementSibling;

如果指定元素是父级下的最后一个元素,那么nextElementSibling 返回 null

let current = document.querySelector('.current');
let nextSibling = current.nextElementSibling;
console.log(nextSibling);

// 输出:
// <li>博客</li>

获取指定元素的所有下一个相邻的兄弟元素,我们可以加个while循环

let current = document.querySelector('.current');
let nextSibling = current.nextElementSibling;

while(nextSibling) {
  console.log(nextSibling);
  nextSibling = nextSibling.nextElementSibling;
}

上一个兄弟元素

同理,获取上一个兄弟元素,使用 previousElementSibling 属性

let current = document.querySelector('.current');
let prevSibling = currentNode.previousElementSibling;

如果指定元素是父级下的第一个元素,那么previousElementSibling 返回 null

let current = document.querySelector('.current');
let prevSiblings = current.previousElementSibling;
console.log(prevSiblings);

// 输出:
// <li>产品</li>

同理,获取指定元素的所有上一个相邻的兄弟元素,我们可以加个while循环

let current = document.querySelector('.current');
let prevSibling = current.previousElementSibling;
while(prevSibling) {
  console.log(prevSibling);
  prevSibling = prevSibling.previousElementSibling;
}

获取所有兄弟元素

要获取指定元素的所有兄弟元素,我们可以按照下面逻辑

  • 首先查找指定元素的父元素,如果没有返回,说明没有任何兄弟元素
  • 第二获取父元素下的第一个子节点
  • 第三将第一个元素添加到siblings数组中
  • 第四选择第一个元素的下一个兄弟元素
  • 最后,循环三、四步骤,直到没有下一个兄弟元素节点
let getSiblings = function (e) {
  // 存储所有兄弟元素
  let siblings = []; 
  // 如果没有父元素,返回
  if(!e.parentNode) {
    return siblings;
  }
  // 父元素的第一个子元素
  let sibling  = e.parentNode.firstChild;

  // 循环,记录所有兄弟元素
  while (sibling) {
    if (sibling.nodeType === 1 && sibling !== e) {
      siblings.push(sibling);
    }
    sibling = sibling.nextSibling;
  }
  
  return siblings;
};

示例代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JavaScript Siblings</title>
</head>
<body>
  <ul id="menu">
    <li>首页</li>
    <li>产品</li>
    <li class="current">新闻</li>
    <li>博客</li>
    <li>投资者</li>
    <li>文档</li>
    <li>关于我们</li>
  </ul>
    
  <script>
    let getSiblings = function (e) {
      // 存储所有兄弟元素
      let siblings = []; 
      // 如果没有父元素,返回
      if(!e.parentNode) {
        return siblings;
      }
      // 父元素的第一个子元素
      let sibling  = e.parentNode.firstChild;

      // 循环,记录所有兄弟元素
      while (sibling) {
        if (sibling.nodeType === 1 && sibling !== e) {
          siblings.push(sibling);
        }
        sibling = sibling.nextSibling;
      }

      return siblings;
    };

    let siblings = getSiblings(document.querySelector('.current'));
    siblingText = siblings.map(e => e.innerHTML);
    console.log(siblingText);
  </script>
</body>
</html>

上面代码将输出:

['首页', '产品', '博客', '投资者', '文档', '关于我们']

总结

这些很基础的DOM操作API可能平时大家用的比较少,都是借助于JQuery或者Vue、React这些MVVM这些框架,但大家要明白这些技术的底层原理也是这些很基础的DOM操作,只不过把脏活累活都帮你干了。

今天就到这里,明天继续讲讲动态创建DOM元素、动态插入。

如果你想跟着我一起复习DOM知识,微信搜索【小帅的编程笔记】,每天更新