DOM(一)概述、dom树、查找元素

简介: DOM(一)概述、dom树、查找元素

一、DOM 概述

       DOM全称 Document Object Model,是专门操作网页内容的一套对象和函数的总称。由于 ES 标准中只规定了 js 语言的核心语法,并没有规定如何使用 js 操作网页的内容,所以在今后只要想操作网页中的内容时,就必须用 DOM。


       DOM 标准是由 W3C 制定的国际标准,由 W3C 负责制定并维护,且几乎所有浏览器100%兼容。包括:增、删、改、查、事件绑定。


对比DOM与其他框架:


       原生DOM,万能,但很繁琐;


       jQuery函数库,简单,但没有减少步骤;


       Vue框架;自动化,简化步骤,但有兼容性问题。


二、DOM树

       一个网页的所有内容,在浏览器内存中,都是以树形结构保存的,树形结构是最直观的展现上下级包含关系的结构。而网页内容中的元素结构,也是上下级包含关系。      


       浏览器读取到一个网页的内容,都会先在内存中创建一个唯一的树根节点对象: document;浏览器扫描网页内容,每扫描到一项内容(元素、文本、属性...),就会自动创建一个新的节点对象(Node),保存当前这一项内容的属性和值。然后将新创建的节点对象,保存到DOM树上对应的位置。


       树形结构如下图:

image.png



二、查找元素

1. 无需查找的元素

       不需要查找,就可直接获得的元素/对象有 4个;


(1)根节点对象:document


(2)html元素节点对象:document.documentElement


(3)head元素节点对象:document.head


(4)body元素节点对象:document.body


举例如下:


<body>
  <span id="s1">Hello</span>
  <h1>标题一</h1>
  <script>
  //console.log 输出的不是对象存储结构,而是DOM树结构(节点间关系)
  console.log(document);
  console.log(document.documentElement);
  console.log(document.head);
  console.log(document.body);
  //console.dir 输出一个节点对象在内存中的属性结构
  console.dir(document);
  console.dir(document.documentElement);
  console.dir(document.head);
  console.dir(document.body);
  </script>
</body>

打印效果如下:

image.png

2. 按节点间关系查找

       按照元素在 DOM 树中的上下级或平级关系查找其它元素;如果已经获得一个 DOM 元素对象,想找这个 DOM 元素对象周围附近的元素时,才用节点间关系。分为节点树和元素树两种:


节点树(包含所有网页内容的完整树结构)


父子关系

image.png

节点对象.previousSibling

获得一个节点对象相邻的下一个兄弟节点对象 节点对象.nextSibling

       节点树会将看不见的回车、空格等空字符也创建为节点对象。严重干扰我们的查找结果!所以,今后几乎不用节点树。


元素树(仅包含元素节点的树形结构)


父子关系

获得一个元素对象的父级元素对象

image.png


image.png

元素对象.previousElementSibling

获得一个元素对象相邻的下一个兄弟元素对象 元素对象.nextElementSibling

       元素树避免了节点树的缺点,不会受到看不见的空字符的干扰,所以将来只要按节点间关系查找元素时,都用元素树。举例:


<body>
  <span id="s1">Hello</span>
  <h1>标题一</h1>
  <script>
    //获得body的第一个直接子元素span
    var span = document.body.firstElementChild;
    console.log(span);
    //获得span的下一个兄弟h1
    var h1 = span.nextElementSibling;
    console.log(h1);
    //获得body下所有直接子元素的集合:3个元素
    var ele = document.body.children;
    console.log(ele);
  </script>
</body>

打印结果如下:

image.png

3. 按 HTML 特征查找

(1)按 id 名查找一个元素

var 一个元素对象 = document.getElementById("id名");

       意为在整个页面中通过 id 名来查找元素;如果找到符合要求的元素,则只返回一个元素对象,如果没找到,则返回 null。


注意:


       . 前的主语必须是 document;


       因为只找一个元素,所以函数名中 Element 没有 s 结尾,是单数形式。


(2)按标签名查找多个元素


var 类数组对象 = 任意父元素.getElementsByTagName("标签名");

       在指定父元素范围内通过标签名获取多个元素;如果找到符合要求的元素,就返回类数组对象如果没找到,返回空类数组对象: { length:0 }。


注意:


       因为找到多个元素,所以返回值为类数组对象;


       最好指定只在一个父元素范围内查找符合要求的元素,查找范围越小,查找越快;


       因为找到多个元素,所以函数名中的 Elements以s 结尾,表示复数;


       不仅查找直接子元素,而且会在所有后代元素中查找符合要求的元素;


       如果这个函数规定要返回类数组对象,那么在任何时候,都会返回类数组对象!即使只找到一个元素,也会把这唯一的一个元素放在类数组对象中第一个位置返回。所以,如果只找到一个符合要求的元素时,必须用[0],取出类数组对象中第一个位置保存的元素对象,才能对这个元素对象继续执行后续操作。


(3)按 class 名查找多个元素


var 类数组对象 = 任意父元素.getElementsByClassName("class名");

       在指定父元素范围内通过 class 名获取多个元素;如果找到符合要求的元素,就返回类数组对象,如果没找到,返回空类数组对象: {length:0 }。


注意:


       因为找到多个元素,所以返回值为类数组对象


       最好指定只在一个父元素范围内查找符合要求的元素。——优化,查找范围越小,查找越快!


       因为找到多个元素,所以函数名中的Elements以s结尾,表示复数


       不仅查找直接子元素,而且会在所有后代元素中查找符合要求的元素。


       如果这个函数规定要返回类数组对象,那么在任何时候,都会返回类数组对象!即使只找到一个元素,也会把这唯一的一个元素放在类数组对象中第一个位置返回。所以,如果只找到一个符合要求的元素时,必须用[0],取出类数组对象中第一个位置保存的元素对象,才能对这个元素对象继续执行后续操作!


(4)按 name 名查找多个表单元素


var 类数组对象 = document.getElementsByName("name名");

        在整个页面范围内通过 name 名获取多个元素;如果找到符合要求的元素,就返回类数组对象如果没找到,返回空类数组对象: {length:0}。


注意:


       .前必须是document,不能改为其它任意元素


       因为可能找到多个,所以也返回类数组对象


       因为可能找到多个,函数名中的Elements也是s结尾,表示复数


       如果这个函数规定要返回类数组对象,那么在任何时候,都会返回类数组对象!即使只找到一个元素,也会把这唯一的一个元素放在类数组对象中第一个位置返回。所以,如果只找到一个符合要求的元素时,必须用[0],取出类数组对象中第一个位置保存的元素对象,才能对这个元素对象继续执行后续操作!


举例:查找指定的元素,并修改元素的样式;


<script>
  //查找id为nav的一个ul元素
  var ulNav = document.getElementById("nav");
  console.log(ulNav);
  //在id为nav的ul下查找所有li
  var lis = ulNav.getElementsByTagName("li");
  console.log(lis);
  //在id为nav的ul下查找tr
  var trs = ulNav.getElementsByTagName("tr");
  console.log(trs);
  //在body下查找span元素,并将第一个设置为黄色
  var span = document.body.getElementsByTagName("span")[0];
  console.log(span);
  span.style.color = "yellow";
  //查找id为nav的ul下的所有class为item的元素,并设置边框
  var items = ulNav.getElementsByClassName("item");
  // 对查找到的多个元素统一设置时要先遍历
  for (var item of items) {
    item.style.border = "2px solid blue";
  }
  //查找id为nav的ul下的class为active的一个li,修改其字体颜色为红色,背景色为粉色
  var li = ulNav.getElementsByClassName("active")[0];
  li.style.color = "red";
  li.style.backgroundColor = "pink";
  //查找name为sex的两个单选框并添加阴影
  var radios = document.getElementsByName("sex");
  for (var rad of radios) {
    rad.style.boxShadow = "0 0 10px black";
  }
  //查找一个name为uname的元素,为其添加阴影效果
  var xm = document.getElementsByName("uname")[0];
  xm.style.boxShadow = "0 0 5px red";
  </script>

显示结果如下:

image.png



4. CSS 选择器查找


(1)只查找一个符合要求的元素


var 一个元素对象 = 任意父元素.querySelector("选择器");

(2)查找多个符合要求的元素


var 类数组对象 = 任意父元素.querySelectorAll("选择器");

DOM四步:


       1. 查找触发事件的元素

       2. 绑定事件处理函数

       3. 查找要修改的元素

       4. 修改元素<(1)先取出旧值(2)做计算(3)放回元素中>


三、案例:通过DOM实现购物车效果

HTML、CSS结构如下

<table id="data">
  <thead>
    <tr>
    <th>商品名称</th>
    <th>单价</th>
    <th>数量</th>
    <th>小计</th>
    </tr>
  </thead>
  <tbody>
    <tr>
    <td>iPhone6</td>
    <td>¥4488.00</td>
    <td>
      <button>-</button>
      <span>1</span>
      <button>+</button>
    </td>
    <td>¥4488.00</td>
    </tr>
    <tr>
    <td>iPhone6 plus</td>
    <td>¥5288.00</td>
    <td>
      <button>-</button>
      <span>1</span>
      <button>+</button>
    </td>
    <td>¥5288.00</td>
    </tr>
    <tr>
    <td>iPad Air 2</td>
    <td>¥4288.00</td>
    <td>
      <button>-</button>
      <span>1</span>
      <button>+</button>
    </td>
    <td>¥4288.00</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
    <td colspan="3">Total: </td>
    <td>¥14064.00</td>
    </tr>
  </tfoot>
  </table>
table {
  width: 600px;
  text-align: center;
  border-collapse: collapse;
}
td,
th {
  border: 1px solid black
}
td[colspan="3"] {
  text-align: right;
}

页面结构如图


image.png


页面显示效果如图

image.png


需要通过DOM实现3个功能:


       功能1:点击按钮时商品数量变化;

       功能2:数量变化时小计自动计算;

       功能3:自动计算总价。


<script>
  // DOM四步
  // 1.查找所有需要绑定事件的元素,本案例为table中的button
  // 先找table
  var table = document.getElementById("data");
  // 再找button
  var btns = table.getElementsByTagName("button");
  // 2.绑定单击事件处理函数
  // 由于本案例中所有的button都需要绑定事件 ,所以需要先将它们遍历出来
  for (var btn of btns) {
    btn.onclick = function () {
      // 功能1:点击按钮时商品数量变化
      // 3.查找需要修改的元素
      // 需要修改的是span标签中的内容,span是按钮的父级的第二个子级
      var span = this.parentElement.children[1];
      // 4.修改元素
      // 4.1获取span中的旧内容并转为整数
      var n = parseInt(span.innerHTML);
      // 4.2修改需要修改的元素
      // 判断:如果按钮中的内容为+(也就是点击按钮+)时,n+1;否则反之,但n最小为1
      if (this.innerHTML == "+") {
        n++;
      } else if (n > 1) {
        n--;
      }
      // 4.3最后将新的n值再赋给旧的span
      span.innerHTML = n;
      // 功能2:数量变化时小计自动计算
      // 3.查找需要修改的元素
      // 需要修改的为button父级的下一个兄弟元素td
      var tdSub = this.parentElement.nextElementSibling;
      // 4.修改元素
      // 4.1获取button的父级的上一兄弟的内容(单价)并去掉人民币符号
      var price = parseFloat(this.parentElement.previousElementSibling.innerHTML.slice(1));
      // 4.2计算小计
      var sub = price * n;
      // 4.3再将小计内容放回下一兄弟td(小计)
      tdSub.innerHTML = (`¥${sub.toFixed(2)}`);
      // 功能3:计算总价
      // 3.查找需要修改的元素
      // 需要的修改的为tfoot下tr的最后一个td(总价)
      var totalTd = table.querySelector("tfoot td:last-child");
      // 4.修改元素
      // 4.1获取所有行中的最后一个td的内容(小计)
      var tds = table.querySelectorAll("table td:last-child");
      // 4.2遍历找到的每个td,并进行计算
      var total = 0;
      for (var td of tds) {
        total += parseFloat(td.innerHTML.slice(1));
      }
      // 4.3将总计total保留两位小数放入总计td中
      totalTd.innerHTML = (`¥${total.toFixed(2)}`);
    }
  }
</script>

案例效果如下

image.png

单击添加按钮后,小计和总计都会做出相应计算:

image.png


相关文章
|
17天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的DOM节点树。通过循环节点,可以访问并处理每个元素,如提取值。示例代码展示了加载XML字符串到`xmlDoc`后,遍历根元素的所有子节点,打印出节点名及文本值,例如:&quot;title: Everyday Italian&quot;、&quot;author: Giada De Laurentiis&quot;和&quot;year: 2005&quot;。
|
23小时前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的节点树。通过示例代码展示如何使用DOM解析XML,遍历根元素的所有子节点,打印出节点名称和文本值。实例中,XML包含书籍信息,程序遍历显示了标题、作者和年份。
|
2天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的节点树。通过循环移动,可以访问并处理每个节点,例如提取元素值。示例代码展示了一个实例,它加载XML字符串到`xmlDoc`,遍历根元素的所有子节点,打印出节点名及文本值。
|
7天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍如何遍历XML文档的节点树。通过循环移动,提取每个元素的值。示例代码展示了一个实例,它加载XML字符串到`xmlDoc`,然后遍历根元素的所有子节点,打印出节点名称及文本值。输出包括:`title: Everyday Italian`, `author: Giada De Laurentiis`, `year: 2005`。
|
9天前
|
前端开发 JavaScript
HTML DOM如何通过JavaScript动态改变元素的CSS样式?
【5月更文挑战第23天】HTML DOM如何通过JavaScript动态改变元素的CSS样式?
16 1
|
12天前
|
XML JavaScript 前端开发
XML DOM 遍历节点树
```markdown 遍历XML DOM节点树涉及在文档中循环移动。以下示例展示如何遍历并显示所有子节点的名称和值: ``` ```xml &lt;!DOCTYPE html&gt; &lt;output&gt; title: Everyday Italian author: Giada De Laurentiis year: 2005 &lt;/output&gt; ``` ```javascript // 加载XML到xmlDoc // 获取根元素子节点 // 对每个子节点,打印节点名和文本节点值 ```
|
14天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的节点树。通过循环移动,可以访问并处理每个节点,例如提取元素值。提供的实例展示了如何加载XML到DOM,获取根元素的子节点,并打印其名称和值,以“title: Everyday Italian, author: Giada De Laurentiis, year: 2005”为例。
|
14天前
|
JavaScript 前端开发 架构师
Web Components:自定义元素与Shadow DOM的实践
Web Components是用于创建可重用自定义HTML元素的技术集合,包括Custom Elements、Shadow DOM、HTML Templates和Slots。通过Custom Elements定义新元素,利用Shadow DOM封装私有样式,&lt;slot&gt;元素允许插入内容。自定义元素支持事件处理和属性观察,可复用且样式隔离。它们遵循Web标准,兼容各前端框架,注重性能优化,如懒加载和Shadow DOM优化。
16 0
|
16天前
|
存储 移动开发 JavaScript
jQuery 根据 css 类筛选 DOM 元素的代码
jQuery 根据 css 类筛选 DOM 元素的代码
27 1
|
16天前
|
移动开发 JavaScript 前端开发
jQuery 根据 DOM 元素 attribute 进行过滤的语法
jQuery 根据 DOM 元素 attribute 进行过滤的语法
18 2