12DOM

本文介绍了DOM的基本概念,包括如何通过JavaScript获取和操作文档节点,如元素节点、文本节点和属性节点。还详细讲解了事件绑定、事件处理以及文档加载时机的选择。此外,文中还提供了DOM操作的实例,如切换图片、选择喜好和修改元素样式。
摘要由CSDN通过智能技术生成

DOM

Hello World

<body>
  <button id="btn"> </button>
  <!-- 使用DOM控制页面 -->
  <script>
    let btn = document.getElementById('btn');
    btn.innerHTML = "Hello World";
  </script>
</body>

DOM(Document Object Model):

  • DOM是Web Api 中的一部分即文档对象模型
  • DOM把网页中所有的内容转化为对象,然后在对其进行操作来控制页

获取文档节点(document)

文档节点(document)对象:

  • document代表整个网页

document对象的原型链:

  • HTMLDocument --> Document --> Node --> EventTarget --> Object.prototype --> null
  • 凡是在原型链上存在的对象的属性和方法都可以通过Document去调用

Document的部分属性:

实例属性:

  • document.documentElement --> 获取html根元素
  • document.head --> 获取head元素
  • document.title --> 获取title元素
  • document.body --> 获取body元素
  • document.links – >获取页面中所有的超链接

获取元素节点(element)

<body>
<div><button id="btn">按钮</button></div>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<div>我是div
  <div class="d">dddd</div></div>
  <span>ssss</span>
</div>
<div>我是div</div>
<div>我是div</div>
<script>
//根据获取id元素节点对象
const btn = document.getElementById('btn');
//根据获取class元素节点对象
const s1 = document.getElementsByClassName('s1');
//根据获取标签名元素节点对象
    const divs = document.getElementsByTagName('div');
//根据选择器来获取元素节点对象
const s2 = document.querySelectorAll('div');
const btn2 = document.querySelector('#btn');
const btn3 = document.querySelector('div #btn');
//创建一个元素节点对象
const c = document.createElement('h2');
</script>
</body>

元素节点(element)对象:

  • 在网页中每一个标签都是一个元素节点
  • 我们可以通过document获取已有的节点创建没有的节点

通过doucment来获取已有的元素节点:

  • document.getElementById():根据id获取一个元素节点对象
  • document.getElementsByClassName():根据元素的Class属性来获取一组元素节点对象,返回一个类数组对象,且可以实时刷新
  • document.getElementsByTagName():根据标签名来获取一组元素节点对象,返回一个类数组对象,且能实时刷新
  • document.getElementsByName():根据name属性来获取一组元素节点对象,返回一个类数组对象,且能实时刷新,一般用于获取表单的元素节点对象
  • document.querySelectorAll():根据选择器来获取一组元素节点对象,返回一个类数组,但不能实时刷新
  • document.querySelector():根据选择器获取一个元素的节点对象,但会第一个符合条件的元素节点对象不能实时刷新

**通过document**来创建一个新的元素节点对象:

  • document.createElement():创建一个新的元素节点对象(但不会直接插入到网页中)

属性和方法

<body>
<div id="box1">
  我是div
  <span class="s1">我是div内的span</span>
  <span class="s1">我是div内的span</span>
</div>
<span class="s1">div里的span</span>
<script>
//获取class属性为s1的元素节点
const s = document.getElementsByClassName('s1');
//获取id属性为div的元素节点
const box = document.getElementById('box1');
    //通过div这个元素节点对象来获取其他的节点
//获取box下的class属性为s1的元素节点
const boxs = box.getElementsByClassName('s1');
//获取box下的所有子节点(包括文本节点:文字, 注释, 换行)
const s1 = box.childNodes;
//获取box下的所有元素节点
const s2 = box.children;
</script>
</body>

div的原型链:

  • HTMLDivElement --> HTMLElement --> Element --> Node --> EventTarget --> Object.prototype --> null

通过元素节点对象来获取其他节点:

  • element.childNodes获取当期元素下的所有子节点(包括文本节点:文字,注释,换行)
  • element.children获取当前元素下的所有元素节点
  • element.firstElementChild获取当前元素下的第一个子节点
  • element.lastElementChild获取当前元素下的最后一个子节点
  • element.nextElementSibling获取当前元素的下一个兄弟元素
  • element.previousElementSibling获取当前元素的前一个兄弟元素
  • element.parentNode获取当前元素的父节点
  • element.tagName获取当前元素的标签名

获取文本节点(text)

<body>

  <div></div>
<div id="box1">
  我是div
  <span class="s1" style="display: none">我是div内的span</span>
  <span class="s1">我是div内的span</span>
</div>
    
<span class="s1">div外的span</span>
<script>
const box = document.getElementById('box1');
console.log(box.textContent);
console.log(box.innerText);
console.log(box.innerHTML)
box.innerText = '<li>我是li标签</li>';
box.textContent = '<li>我是li标签</li>';
box.innerHTML = '<li>我是li标签</li>';
</script>
</body>

在DOM中所有文本内容都是文本节点对象,可以通过元素来获取其中的文本节点对象,但是我们通常不这么做,一般会直接通过元素去修改其中的文本

通过元素节点对象直接修改文本的三个属性:

  • element.textContent获取或修改元素中的文本内容,只获取标签里的内容,且不会考虑css样式
  • element.innerText获取或修改元素中的文本内容,获取内容时会考虑css样式(读取,计算css样式,触发网页重排),字符串中有标签时,会自动对标签进行转义(<li>--> &lt;li&gt;)
  • element.innerHTML获取或修改元素中的html代码,可以直接向元素中添加html代码,通过innerHTML向网页插入元素时,有被xss注入的风险

获取属性节点(Attr)

<body>
<input class="in" type="text" value="张三" name="username" disabled>
<div class="box">
  我是div
  <a class="box-a" href="">我是div里的a标签</a>
</div>
<script>
//获取元素节点对象
const n = document.getElementsByName('username')[0];
const n1 = document.querySelector('.box');
const n2 = document.querySelector('.box a');
console.log(n);
console.log(n1);
console.log(n2);
//通过元素节点对象来对属性节点进行操作
// 方式一
// 读取
console.log(n.value, n.type, n.name, n.className, n.disabled);
// 修改
console.log(n.value = '李四', n.className = 'xg', n.disabled = false, n.type = 'button');
n1.style = 'color: red';
n2.href = 'https://baidu.com'
// 方式二
// 读取
console.log(n.getAttribute('type'), n.getAttribute('value'), n.getAttribute('name'), n.getAttribute('class'));
// 修改
console.log(n.setAttribute('type', 'text'), n.setAttribute('value', '瑞克'), n.setAttribute('name', 'modi'), n.setAttribute('class', 'll'));
n1.setAttribute('style', 'background: yellowgreen');
n2.setAttribute('style', 'text-decoration: none');
//  删除
console.log(n.removeAttribute('disabled'));
</script>
</body>

属性节点(Attr):

  • 在DOM中也是一个对象,通常不需要获取对象而是直接通过元素直接对其进行各种操作

操作属性节点:

方式一:

  • 读取: 元素.属性名(注意class属性需要使用className来读取),读取一个布尔值时返回true或false
  • 修改:元素.属性名 = 属性值

方式二:

  • 读取:元素.getAttribute(属性名)
  • 修改:元素.setAttribute(属性名, 属性值)
  • 删除:元素.removeAttribute(属性名)

事件(event)

<body>
<!-- 方式1 -->
<button id="btn" onclick="alert('hello')" >点击事件</button>
<script>
//方式2:为元素指定的属性绑定事件的回调函数
//获取元素节点对象
const btn = document.querySelector('#btn');
console.log(btn);
btn.onclick = function() {
  document.querySelector('body').style = 'background: #bfa';
}
// 方式3: 通过元素的addEventListener()方法来绑定事件
btn.addEventListener('click', function() {
  // document.write('sh');
  document.querySelector('body').innerHTML = '<div>增加</div>'
});
</script>
</body>

事件(event):

  • 事件就是用户和页面之间的交互行为(例如:点击按钮,鼠标移动,敲击键盘等)
  • 可以通过为事件绑定响应函数(回调函数),来完成和用户之间的交互

绑定响应函数的方式:

  • 可以直接在元素的属性中设置
  • 可以通过为元素的指定的属性设置回调函数的形式来绑定事件(一个事件只能绑定一个响应函数)
  • 可以通过元素的addEventListener()方法来绑定事件

文档的加载

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      background-color: rgba(77, 119, 68, 0.47);
      /* text-align: center;
      margin-top: 300px */
    }
  </style>
  <script>
    // 3.js代码编写在DOMContentLoaded回调函数中
    document.addEventListener('DOMContentLoaded', function(){
      const btn = document.querySelector('#btn');
    });
    // 4.js代码编写在window.onload回调函数中
    window.onload = function() {
      const btn = document.querySelector('#btn');
    }
  </script>
  <!--2. 以defer的形式引入外部js文件 -->
  <script defer src="./01helloModule.js"></script>
</head>
<body>
<button id="btn">点击事件</button>
<!--1. js代码编写在body的底部(最快最有效) -->
<script>
const btn = document.querySelector('#btn');
alert(btn);
</script>
<script src="./01helloModule.js"></script>
</body>

文档的加载:

  • 网页的加载时自上向下进行的,如果把js代码编写在网页的上边,会导致js代码在执行时,网页还没加载完毕,会出现无法获取DOM对象的情况

js代码编写位置:

  • 将js标签编写在body的底部(最快最有效)
  • 引入外部js时,以defer的形式进行引入(第二快)
  • 将js代码编写到document对象的DOMContentLoaded的回调函数中(第三快)
  • 将js代码编写到window.onload的回调函数中(第四快)

DOM操作练习

1.点击切换图片

<body>
  <div class="outer">
    <p id="info">当前是第1张,一共7张图片</p>
    <div class="img-warpper">
      <img style="width: 720px; height: 400px;" src="./img/01.jpeg" alt="">
    </div>
    <div class="btn-warpper">
      <button id="prev">上一张</button>
      <button id="next">下一张</button>
    </div>
  </div>
  <!-- js -->
  <script>
    // 点击按钮切换图片
    // 获取info
    const info = document.querySelector('#info');
    // 获取图片
    const imgs = document.querySelector('img');
    // 获取按钮
    const prev = document.querySelector('#prev');
    const next = document.querySelector('#next');
    // 方式1 (丧失灵活性)
    // 绑定点击事件
    // 上一张
    let i = 1;
    // info.textContent = `当前是第${i}张,一共7张图片`;
    prev.onclick = function() {
      i--;
      imgs.src = `./img/0${i}.jpeg`
      if(i <= 0) {
        i = 7;
        imgs.src = `./img/0${i}.jpeg`
      }
      info.textContent = `当前是第${i}张,一共7张图片`;
    }
    // 下一张
    next.onclick = function() {
      if(i<7) {
        imgs.src = `./img/0${++i}.jpeg`;
      }else if(i == 7) {
        i = 1;
        imgs.src = `./img/0${i}.jpeg`
      }
      info.textContent = `当前是第${i}张,一共7张图片`;
    }
    方式2
    const arr = [
      './img/01.jpeg',
      './img/02.jpeg',
      './img/03.jpeg',
      './img/04.jpeg',
      './img/05.jpeg',
      './img/06.jpeg',
      './img/07.jpeg',
    ];
    let a = 0;
    // 上一张
    prev.onclick = function() {
      a--;
      if(a < 0) {
        a = arr.length - 1;
      }
      info.textContent = `当前是第${a + 1}张,一共${arr.length}张图片`;
      imgs.src = arr[a];
    }
    // 下一张
    next.onclick = function() {
      a++;
      if(a > arr.length -1) {
        a = 0
      }
      info.textContent = `当前是第${a + 1}张,一共${arr.length}张图片`;
      imgs.src = arr[a];
    }
  </script>
</body>

2.点击按钮选择喜好

<body>
  <div>
    <form action="#">
      <div>
        请选择你的爱好:
        <input type="checkbox" id="check-all">全选
      </div>
      <div>
        <input type="checkbox" name="hobby" value="动漫">动漫
        <input type="checkbox" name="hobby" value="电影">电影
        <input type="checkbox" name="hobby" value="游戏">游戏
        <input type="checkbox" name="hobby" value="学习">学习
      </div>
      <div>
        <button type="button" id="all">全选</button>
        <button type="button" id="no">取消</button>
        <button type="button" id="reverse">反选</button>
        <button id="send">提交</button>
      </div>
    </form>
  </div>
  <script>
    // 按钮全选功能
    // 获取全选按钮
    const btn = document.getElementById('all');
    // 获取四个多选框
    const hobbys = document.getElementsByName('hobby');
    // 为全选按钮绑定单击事件
    btn.onclick = function () {
      //遍历多选框
      for (let i = 0; i < hobbys.length; i++) {
        hobbys[i].checked = true;
      }
      checkAll.checked = true;
    }
    // 取消全选按钮功能
    // 获取取消按钮
    const no = document.getElementById('no');
    no.onclick = function () {
      for (let i = 0; i < hobbys.length; i++) {
        hobbys[i].checked = false;
      }
      checkAll.checked = false;
    }
    //反选按钮
    // 获取反选按钮
    const reverse = document.getElementById('reverse');
    reverse.onclick = function () {
      for (let i = 0; i < hobbys.length; i++) {
        hobbys[i].checked = !hobbys[i].checked;
      }
      const checkBox = document.querySelectorAll('[name = hobby]:checked');
      checkBox.length === hobbys.length ? checkAll.checked = true : checkAll.checked = false;
    }
    //提交按钮
    // 获取提交按钮
    const send = document.getElementById('send');
    send.onclick = function () {
      for (let i = 0; i < hobbys.length; i++) {
        // hobbys[i].checked && alert(hobbys[i].value);
        if (hobbys[i].checked) {
          alert(hobbys[i].value);
        }
      }
    }
    // 大全选按钮
    // 获取大全选按钮
    const checkAll = document.getElementById('check-all');
    checkAll.onclick = function () {
      for (let i = 0; i < hobbys.length; i++) {
        // if(checkAll.checked) {
        //   hobbys[i].checked = true;
        // }else {
        //   hobbys[i].checked = false;
        // }
        // checkAll.checked ? hobbys[i].checked = true : hobbys[i].checked = false;
        // hobbys[i].checked = checkAll.checked;
          //在事件的响应函数中,this指向响应函数绑定的对象(箭头函数除外)
        hobbys[i].checked = this.checked;
      }
    }
    for (let i = 0; i < hobbys.length; i++) {
        hobbys[i].onclick = function() {
          const checkBox = document.querySelectorAll('[name = hobby]:checked');
          // alert(checkBox.length);
         checkBox.length === hobbys.length? checkAll.checked = true : checkAll.checked = false;
        }
      }
  </script>
</body>

document.querySelectorAll('[name = hobby]:checked'):

  • :checked伪类选择器,只返回checked为true时的元素

在事件的响应函数中,this指向响应函数绑定的对象(箭头函数除外)

元素的修改

<body>
<button id="btn1">添加</button>
<button id="btn2">替换</button>
<button id="btn3">删除</button>
<hr></hr>
<ul id="list">
  <li id="zs">张三</li>
  <li id="ls">李四</li>
  <li id="rk">瑞克</li>
</ul>
<script>
const list = document.getElementById('list');
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
const btn3 = document.getElementById('btn3');
// 添加
btn1.onclick = function() {
  // 添加节点
  const li = document.createElement('li');
  // 添加文本
  li.textContent = '莫蒂';
  // 添加属性
  li.id = 'md';
  console.log(li);
  // 添加到DOM
  // 为一个节点添加子节点
  list.appendChild(li); //只能在结尾添加节点
  list.insertAdjacentElement('beforeend', li); //可以在(子元素,或当前元素)开头,结尾添加节点
}
list.insertAdjacentHTML('afterbegin', '<li id="jk">杰克</li>');
//替换
btn2.onclick = function() {
  const li = document.createElement('li');
  li.textContent = '汤姆';
  li.id = 'tm';
  // 获取zs
  const zs = document.getElementById('zs');
  // 替换zs
  zs.replaceWith(li);
}
// 删除
btn3.onclick = function() {
  // 获取zs
  const zs = document.getElementById('zs');
    //id选择器不用获取元素对象也能进行操作
  // 删除zs
  zs.remove();
}
</script>
</body>

添加:

  • appendChild()给一个节点添加子节点(只能在末尾添加子节点)
  • insertAdjacentElement()可以在(子元素,或当前元素)开头,结尾添加节点
    • beforeend标签的最后
    • afterbegin标签的开始
    • beforebegin当前元素的前边插入元素(兄弟元素)
    • afterbegin当前元素的后边插入元素**(兄弟元素**)
  • insertAdjacentHTML('<li id="id">xx</li>')

替换:

  • replaceWith()使用一个元素替换一个元素

删除:

  • remove()删除一个元素

练习

<body>
<div class="outer">
  <table>
    <tbody>
      <tr>
        <th>姓名</th>
        <th>邮件</th>
        <th>薪资</th>
        <th>操作</th>
      </tr>
      <tr>
        <td>张三</td>
        <td>zs@qq.com</td>
        <td>13000</td>
        <td><a href="#">删除</a></td>
      </tr>
      <tr>
        <td>李四</td>
        <td>ls@qq.com</td>
        <td>10000</td>
        <td><a href="#">删除</a></td>
      </tr>
      <tr>
        <td>王五</td>
        <td>ww@qq.com</td>
        <td>15000</td>
        <td><a href="#">删除</a></td>
      </tr>
    </tbody>
  </table>
<form action="#">
<div>
<label for="name">姓名</label>
<input type="text" id="name">
</div>
<div>
<label for="email">邮件</label>
<input type="email" id="email">
</div>
<div style="margin-left: 46px">
<label for="salary">薪资</label>
<input type="number" id="number">
<button id="btn">添加</button>
</div>
</form>
</div>
<script>
//删除员工
  // 获取删除超链接
  const links = document.links;
  // 绑定单击响应函数
  function delEmp() {
    // this指向绑定的响应函数绑定的对象
    // console.log(this);
    // 获取tr
    const tr = this.parentNode.parentNode;
    // 获取tr下的第一个td
    const td = tr.getElementsByTagName('td')[0].textContent;
    // 弹出提示框
    let flag = confirm(`确认要删除[${td}]吗?`)
    // 删除tr
    flag? tr.remove() : '';
    // 取消a标签超链接的默认行为
    return false
  }
for (let i=0; i<links.length; i++){
  links[i].onclick = delEmp;
}
//添加员工
  // 获取按钮 
  const btn = document.getElementById('btn');
  // 获取tbody
  const tbody = document.querySelector('tbody');
  // 绑定单击响应函数
  btn.onclick = function() {
    // 获取文本框的值
    const name = document.getElementById('name').value;
    const email = document.getElementById('email').value;
    const number = document.getElementById('number').value;
    // 添加到 DOM(容易被xss攻击)
    tbody.insertAdjacentHTML('beforeend',
    `
    <tr>
        <td>${name}</td>
        <td>${email}</td>
        <td>${number}</td>
        <td><a href="#">删除</a></td>
    </tr>
    `
    );
    const last = tbody.lastElementChild.lastElementChild.lastElementChild;
    last.onclick = delEmp;
    console.log(last)
    // links[links.length - 1].onclick = delEmp;
    return false;
  }
</script>
</body>

取消标签的默认行为:

  • 设置javascript:;表示引用一个空的js代码(只针对a标签的href属性)
  • 在单击响应函数里添加return false表示不执行标签的默认行为只适用于xx.xx = function(){})

节点的复制

<body>
  <button id="btn">点我复制</button>
  <ul id="list1">
    <li id="l1">张三</li>
    <li id="l2">李四</li>
    <li id="l3">王五</li>
  </ul>
  <ul id="list2">
    <li>杰克</li>
  </ul>
  <script>
    const btn = document.getElementById('btn');
    const list2 = document.getElementById('list2');
    const l1 = document.getElementById("l1");
    btn.onclick = function() {
      // list2.appendChild(l1);
      // 复制l1节点
      const newL1 = l1.cloneNode(true);
      newL1.id = 'newL1';
      list2.appendChild(newL1);
    }
  </script>
</body>

复制节点:

  • 元素.cloneNode():方法对节点进行复制时,他会复制节点的所有特点(包括各种属性),该方法默认只会复制当前节点,不会复制节点的节点,传递参数true作为参数时,会赋值文本节点.

元素的样式

<body>
  <button id="btn">点击获取样式</button>
  <div class="box1"></div>
  <script>
    const btn = document.getElementById('btn');
    const box1 = document.getElementsByClassName('box1')[0];
    btn.onclick = function() {
      const styleObj = getComputedStyle(box1);
      console.log(styleObj); //获取所有样式声明
      console.log(styleObj.width);
        //返回的width值是一个字符串因此在增加宽度时通过parsetInt取整后在计算
      box1.style.width = parseInt(styleObj.width) + 100 + 'px';
      // 获取box1的背景样式(注意写法改为驼峰)
      console.log(styleObj.backgroundColor);
    }
  </script>
</body>

修改:

  • element.style.属性名 = '属性值':修改元素的内联样式,(注意:css样式的属性名如果带有-则需要把属性名改为小驼峰)

读取:

方法:

  • getComputedStyle()😦该方法获取的样式值为字符串)

    • 返回一个对象,该对象包括了当前元素所有的生效的样式
    • 参数:1 获取样式的元素,2:要获取的伪元素
  • 返回对象中的样式值,不一定都可以直接进行计算,因此在使用之前一定要确保值可以进行计算

属性:

  • 获取元素内部的高度与宽度(包括内容区和内边距):
    • 元素.clientHeight | clientWidth
  • 获取元素可见框的高度与宽度(包括内容区和内边距和边框):
    • 元素.offsetHeight | offsetWidth
  • 获取元素滚动区域的高度和宽度:
    • 元素.scrollHeight | scrollWidth
  • 获取元素的定位父元素(如果所有父元素都没开启定位则为body):
    • 元素.offsetParent
  • 获取元素相对于定位父元素的偏移量:
    • 元素.offsetTop | offsetLeft
  • 获取或修改元素滚动条的偏移量:
    • 元素.scrollTop| scrollLeft

操作class改变样式

 <style>    
	.box1 {
      background-color: aqua;
      height: 100px;
    }
    .box2 {
      width: 200px;
      height: 200px;
      background-color: #bfa;
      margin: 10px;
      border: 5px solid yellowgreen;
    }
  </style>
</head>
<body>
  <button id="btn">点击改变样式</button>
  <div class="box1"></div>
  <script>
    const btn = document.getElementById('btn');
    const box1 = document.getElementsByClassName('box1')[0];
    btn.onclick = function() {
      // 通过style属性改变css样式会造成css与js代码的耦合(不完全分离,改变css样式要修改js代码)
      // box1.style.width = '500px';
      // 可以通过为box1添加class类的方法来改变css(不够灵活)
      // box1.className += " box2";
      // 通过classList来修改样式
      // 添加
      // box1.classList.add('box2');
      // 移除
      // box1.classList.remove('box2');
      // 切换
      // box1.classList.toggle('box2')
      // 替换
      box1.classList.replace('box1', "box2");
      // 检查
      console.log(box1.classList.contains('box2'));
    }
  </script>
</body>

元素.classList:的属性的方法

  • 是一个对象,对象提供了对当前元素的类的各种方法
  • 元素.classList.add():为当前元素添加一个类
  • 元素.classList.remove():移除当前元素的一个类
  • 元素.classList.toggle():切换当前元素的类,有则移除没有则添加
  • 元素.classList.replace():替换当前元素的一个类,(不会对其他类产生影响)
  • 元素.classList.contains():检查当前元素是否存在一个类,返回一个布尔值

事件对象

  <style>
    .box1 {
      background-color: aqua;
      height: 200px;
      width: 200px;
    }
    .box2 {
      width: 170px;
      height:170px;
      background-color: #bfa;
    }
    .box3 {
      width: 140px;
      height: 140px;
      background-color: rgb(13, 147, 192);
    }
  </style>
</head>
<body>
  <div class="box1">
    <div class="box2">
      <div class="box3"></div>
    </div>
  </div>
  <a id="baidu" href="https://www.baidu.com">点击跳转百度</a>
  <script>
    const box1 = document.getElementsByClassName('box1')[0];
    const box2 = document.getElementsByClassName('box2')[0];
    const box3 = document.getElementsByClassName('box3')[0];
    const baidu = document.getElementById('baidu');
    // 事件冒泡
    box1.onclick = function(event) {
      // 打印事件对象
      console.log(event);
      // 获取获取触发事件的对象(包含冒泡的触发)
      console.log(event.target);
      // 获取绑定事件的对象(通this)
      console.log(event.currentTarget);
      console.log(this);
      alert('我是box1');
    }
    box2.addEventListener('click', function(event) {
      alert('我是box2');
    })
    box3.onclick = (event) => {
      //停止事件的传递
      event.stopPropagation();
      alert('我是box3');
    }
    baidu.addEventListener('click', (event) => {
      alert('准备跳转');
      // 取消默认行为
      event.preventDefault();
    })
  </script>
</body>

事件对象:

  • 事件对象是浏览器在事件触发时所创建的对象,该对象中封装了事件相关的各种信息
  • 通过事件对象可以获取到事件的详细信息(列如鼠标的坐标,键盘的按键等)
  • 浏览器在创建事件对象后,会将事件对象作为回调函数的参数传递,因此我们需要在回调函数中定义一个形参(一般为event)来接受事件

事件的冒泡(bubble):

  • 事件的冒泡就是指事件的向上传递,当元素上的某个事件被出发后,其祖先元素上的相同事件也会被同时触发
  • 冒泡的存在大大的简化了代码的编写

事件的冒泡(bubble)

  <style>
    .box1 {
      background-color: aqua;
      height: 50px;
      width: 50px;
      border-radius: 50%;
      position: absolute;
    }
    .box2 {
      width: 170px;
      height:170px;
      background-color: #bfa;
    }
    .box3 {
      width: 140px;
      height: 140px;
      background-color: rgb(13, 147, 192);
    }
    .box4 {
      width: 110px;
      height: 110px;
      background-color: rgb(168, 13, 192);
      position: absolute;
      bottom: 0;
    }
  </style>
</head>
<body>
  <div class="box1"></div>
  <div class="box2"></div>
  <div class="box3">
    <div class="box4"></div>
  </div>
  <script>
    const box1 = document.getElementsByClassName('box1')[0];
    const box2 = document.getElementsByClassName('box2')[0];
    const box3 = document.getElementsByClassName('box3')[0];
    const box4 = document.getElementsByClassName('box4')[0];
    // 事件冒泡
    document.onmousemove = function(event) {
      box1.style.left = event.x + 'px';
      box1.style.top = event.y + 'px';
    }
    box2.addEventListener('mousemove', function(event) {
      //停止事件的传递
      event.stopPropagation();
    })
    box3.onmousemove = (event) => {
      alert('我是box3');
    }
    box4.onmousemove = (event) => {
      alert('我是box4');
    }
  </script>
</body>

事件的冒泡与样式无关,与结构相关

事件的委派

<body>
<button id="btn">点击添加超链接</button>
<ul id="list">
  <li><a href="javascript:;">超链接1</a></li>
  <li><a href="javascript:;">超链接2</a></li>
  <li><a href="javascript:;">超链接3</a></li>
</ul>
  <script>
    const btn = document.getElementById('btn');
    const list = document.getElementById('list');
    // 注意: 使用querySelector方法获取的元素节点对象返回的类数组不会实时刷新
    // const links = list.querySelectorAll('a');
    const links = list.getElementsByTagName('a');
    btn.onclick = function(event) {
      list.insertAdjacentHTML('beforeend', "<li><a href='javascript:;'>新超链接</a></li>")
    }
    // 冒泡
    document.addEventListener('click', function(event) {
      // alert(event.target.textContent);
      // 判断事件是否由超链接触发
      console.log([...links]);
      if([...links].includes(event.target)) {
        alert(event.target.textContent);
      }
    })
  </script>
</body>

事件的委派通过冒泡,将本身的事件委派到器祖先元素实现,减少了代码的复杂度

事件的捕获

<body>
<div id="box1">
  <div id="box2">
    <div id="box3"></div>
  </div>
</div>
  <script>
    const box1 = document.getElementById('box1');
    const box2 = document.getElementById('box2');
    const box3 = document.getElementById('box3');
    box1.addEventListener('click', (event) => {
      alert('我是box1' + event.eventPhase);
    }, true);
    box2.addEventListener('click', (event) => {
      alert('我是box2' + event.eventPhase);
    });
    box3.addEventListener('click', (event) => {
      alert('我是box3' + event.eventPhase);
    }, true);
  </script>
</body>

事件的传播机制:

  • 在DOM中,事件的传播可以分为三个阶段:
    1. 捕获阶段(有祖先元素向目标元素进行事件的捕获,默认情况下事件不会在捕获阶段触达)
    2. 目标阶段(触发事件)
    3. 冒泡阶段(由目标元素向祖先元素进行事件的传递)
  • 事件的捕获,指事件有外向内传递(当前元素触发事件后,会从当前元素最大的祖先元素开始向当前元素进行事件捕获)
  • 如果希望事件在捕获阶段开始触发事件,可以将addEventListener的第三个参数设置为true,一般情况下我们不希望在捕获阶段触发事件
  • event.eventPhase可以将事件的传播步骤用数字表示:
    • 1代表捕获阶段
    • 2代表目标阶段
    • 3代表冒泡事件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值