博客列表 >JS基础-DOM操作/HTML节点类型/操作class属性值/元素自定义数据属性操作/元素添加事件处理

JS基础-DOM操作/HTML节点类型/操作class属性值/元素自定义数据属性操作/元素添加事件处理

岂几岂几
岂几岂几原创
2020年06月03日 00:52:202129浏览

DOM 操作

1. DOM 对象

  • 节点: HTML 文件中所有内容都是节点
  • 节点树: 节点按照一定的结构组成的树形结构, 也叫 DOM 树
  • 节点类型: HTML 标签元素, 文本(标签中的文本), 属性(样式属性节点, style), 注释, 文档节点(就是当前 HTML)
  • 访问页面中的内容都要通过 document 对象(文档对象)的属性或者方法
  • 获取元素的返回值, 可以是 HTMLCollection, DOM 元素, NodeList等.
    • HTMLCollection: 类数组(类是”类似”的类), 但并不是数组, 元素键名是从 0 开始, 有一个 length 的属性, 表示其元素数量. 不能使用 forEach 遍历(用 for 遍历). 访问 HTMLCollection 对象的元素的方法:
      • HTMLCollection[index] : 类似数组访问元素的方式.
      • HTMLCollection.item(index) : 通过 HTMLCollection 对象的 item(index) 方法.
      • HTMLCollection.nameItem(元素name属性值) : 通过 HTML Collection 对象的 nameItem() 方法, 传入的参数是要获取的类数组中的元素的 name 属性值.
    • NodeList 类型数据, 取元素值, 同样跟数组类似, 有 length 属性, 有 forEach 和 item 方法.
      • 获取 NodeList 对象中的元素的方法跟数组类似, NodeList.childNodes[0] .
      • 另一种方法: NodeList.item(0) .
      • 可以用 for 或 forEach 遍历 NodeList 中的元素.
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>DOM对象</title>
  7. </head>
  8. <body>
  9. <form action="test1.php"></form>
  10. <form action="test2.php"></form>
  11. <form action="test3.php" id='loginForm' name="login">
  12. <input type="text" name="username" id="username" value="zhangsan">
  13. </form>
  14. </body>
  15. <script>
  16. // 给console.log()函数绑定一个别名
  17. var cl = console.log.bind(console);
  18. // 1. 查看当前文档类型, 即<!DOCTYPE html>
  19. cl(document.doctype);
  20. // 2. 查看根节点, 即<html>元素
  21. /* document并不代表根节点, document.documentElement才是 */
  22. cl(document.documentElement);
  23. // 3. 查看head部分, 即<head>元素
  24. cl(document.head);
  25. // 4. 查看body部分, 即<body>元素
  26. cl(document.body);
  27. /* ↑有了document.head和document.body, 就能使用上下级关系访问节点树中的子节点 */
  28. // 5. 查看<title>元素
  29. /* 方法1: 使用节点树获取 */
  30. cl(document.head.title);
  31. /* 方法2: 使用document对象的title属性获取 */
  32. cl(document.title);
  33. // 6. 获取当前HTML文档中的所有表单
  34. // 6.1 获取表单对象
  35. /* 返回值为: HTMLCollection对象, 类数组, 但并不是数组 */
  36. /* 遍历HTMLCollection对象中的元素, 见temp */
  37. cl(document.forms);
  38. // 6.2 获取表单中的元素/获取HTMLCollection对象中的元素
  39. /* 方法1: 采用类似数组的获取方式. ↓获取第2个表单 */
  40. cl(document.forms[1]);
  41. /* 方法2: 使用HTMLCollection提供的item(元素索引)方法. ↓获取第3个表单 */
  42. cl(document.forms.item(2));
  43. /* 方法3: 根据元素id获取表单(document.getElementById(id值)可以根据id获取所有元素) */
  44. cl(document.getElementById('loginForm'));
  45. /* 方法4: 使用HTMLCollection对象提供的nameItem(name属性值)来获取HTMLCollection中的元素 */
  46. cl(document.forms.namedItem('login'));
  47. // 6.3 获取某个表单中的表单控件的值
  48. /* input:text控件: 表单对象.控件的name属性值.value */
  49. cl(document.forms.item(2).username.value);
  50. </script>
  51. </html>

2. 获取 DOM 元素

  • 通过 document 对象, 利用 HTML 文档元素的树形结构, 可以使用”父级元素. 子级元素”的方式获取 DOM 元素; 也可以使用 document 中提供的一些方法获取到一些固定类型的 DOM 元素, 如: form 元素, title 元素等. 详见 DOM 对象的实例.

  • 还是通过 document 对象提供的方法, 利用元素的属性值来获取 DOM 元素.

    • 2.1 根据标签名来获取元素: document.getElementsByTagName(元素标签名) , 返回值: HTMLCollection 对象;
    • 2.2 根据 id 属性值来获取元素: document.getElementById(id值) , 返回值: DOM 元素(Element 对象).
    • 2.3 根据样式类来获取元素: document.getElementsByClassName(样式类名) , 返回值: HTMLCollection 对象;
    • 2.4 根据 name 属性值来获取元素: document.getElementsByName(name属性值) , 返回值: HTMLCollection 对象;
    • 2.5 根据 css 选择器来获取一个元素: document.querySelector(css选择器表达式) , 返回值: DOM 元素(Element 对象), 若匹配到多个元素, 则返回第一个.
    • 2.6 根据 css 选择器来获取多个元素: document.querySelector(css选择器表达式) , 返回值: 元素数组;
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>获取DOM元素</title>
  7. </head>
  8. <body>
  9. <ul class="list">
  10. <li class="item" name="first">item1</li>
  11. <li class="item" id="item2">item2</li>
  12. <li class="item active">item3</li>
  13. <li class="item">item4</li>
  14. <li class="item" id="item2">item5</li>
  15. </ul>
  16. </body>
  17. <script>
  18. var cl = console.log.bind(console);
  19. // 2.1 根据标签名来获取元素: `document.getElementsByTagName(元素标签名)`, 返回值: HTMLCollection 对象;
  20. /* 获取所有li标签元素 */
  21. var lis = document.getElementsByTagName("li");
  22. cl(lis);
  23. // 2.2 根据 id 属性值来获取元素: `document.getElementById(id值)`, 返回值: DOM 元素(Element 对象).
  24. /* 获取id属性值='item2'的元素, 匹配多个也只取1个 */
  25. var item2 = document.getElementById("item2");
  26. cl(item2);
  27. // 2.3 根据样式类来获取元素: `document.getElementsByClassName(样式类名)`, 返回值: HTMLCollection 对象;
  28. /* 获取设置有.list样式类的元素 */
  29. var ul = document.getElementsByClassName("list");
  30. cl(ul);
  31. /* 获取同时设置有.item和.active样式类的元素 */
  32. var activeItem = document.getElementsByClassName("item active");
  33. cl(activeItem);
  34. // 2.4 根据 name 属性值来获取元素: `document.getElementsByName(name属性值)`, 返回值: HTMLCollection 对象;
  35. /* 获取name属性值为fist的元素, 因返回值是类数组, 所以调用其item(0)方法获取到第一个元素 */
  36. var firstItem = document.getElementsByName("first").item(0);
  37. cl(firstItem);
  38. // 2.5 根据 css 选择器来获取一个元素: `document.querySelector(css选择器表达式)`, 返回值: DOM 元素(Element 对象), 若匹配到多个元素, 则返回第一个.
  39. /* 获取css选择器表达式是.item匹配到的第一个元素 */
  40. var item = document.querySelector(".item");
  41. cl(item);
  42. // 2.6 根据 css 选择器来获取多个元素: `document.querySelector(css选择器表达式)`, 返回值: **元素数组**;
  43. /* 获取css选择器表达式是.item匹配到的所有元素 */
  44. var items = document.querySelectorAll(".item");
  45. cl(items);
  46. /* 获取css选择器表达式是".item:nth-child(-n + 3)"(即前三个)匹配到的所有元素 */
  47. var items = document.querySelectorAll(".item:nth-child(-n + 3)");
  48. cl(items);
  49. /* 遍历这3个元素, 并赋给红色字体样式 */
  50. items.forEach(function (item, index, items) {
  51. item.style.color = "red";
  52. });
  53. </script>
  54. </html>

3. 获取子节点

  • 在 JS 中, 节点类型共有 11 种, 跟 HTML 相关的有 6 种(其他 5 种和 XML 相关), 元素节点只是其中之一.
  • 与 HTML 相关的 6 种元素类型:
    • 元素: 类型值(1);
    • 属性: 类型值(2);
    • 文本: 类型值(3);
    • 注释: 类型值(6);
    • 文档节点: 即 document 对象, 类型值(9);
    • 文档片段: 类型值(11).
  • 获取当前元素的所有类型的子节点: element.childNodes , 返回类型为 NodeList 类型数据, 取元素值, 跟数组类似, 有 length 属性, 有 forEach 和 item 方法.
    • 获取 NodeList 对象中的元素的方法跟数组类似, NodeList.childNodes[0] .
    • 另一种方法: NodeList.item(0) .
    • 用 for 或 forEach 遍历 NodeList 中的元素.
    • 获取节点类型的属性: element.nodeType .
    • 获取节点的名称: element.nodeName .
    • 获取节点的值: element.nodeValue . 只有文本节点才能获得值.
  • 获取当前元素的第一个子节点: element.firstChild .
  • 获取当前元素的最后一个子节点: element.lastChild .
  • 获取当前节点的前一个兄弟节点: element.previousSibling .
  • 获取当前节点的后一个兄弟节点: element.nextSibling .
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>节点类型</title>
  7. </head>
  8. <body>
  9. <ul>
  10. <li>item1</li>
  11. <li>item2</li>
  12. <li>item3</li>
  13. <li>item4</li>
  14. <li>item5</li>
  15. </ul>
  16. </body>
  17. <script>
  18. var cl = console.log.bind(console);
  19. // 获取第一个ul元素
  20. var ul = document.querySelector("ul");
  21. // 1. 获取ul元素的所有类型的子节点
  22. var nodes = ul.childNodes;
  23. /* 包括5个元素类型节点和6个文本类型节点(回车换行) */
  24. cl(nodes);
  25. // 2. 遍历ul元素的子节点, 打印其节点属性信息
  26. nodes.forEach(function (node, index, nodes) {
  27. cl(
  28. "第",
  29. index + 1,
  30. "个节点信息: 节点类型: ",
  31. node.nodeType,
  32. "; 节点名称: ",
  33. node.nodeName,
  34. "; 节点值: ",
  35. node.nodeValue
  36. );
  37. });
  38. // 3. 获取ul元素的第一个子节点
  39. cl(ul.firstChild);
  40. // 4. 获取ul元素的最后一个子节点
  41. cl(ul.lastChild);
  42. // 5. 获取ul元素的第5个子节点的上一个节点/下一个节点
  43. cl(ul.childNodes.item(6).previousSibling);
  44. cl(ul.childNodes.item(6).nextSibling);
  45. </script>
  46. </html>

4. 操作元素的 class 属性

4.1 使用 element.className 操作

  • element.className 以文本的形式返回元素的 class 属性的值.
  • 因为 class 属性名也是 js 的保留字, 所以用 className 来获取 class 属性的值.

4.2 使用 element.classList 操作

  • element.classList 提供了很多便捷的操作 class 属性值的方法
    • element.classList.add(样式类名) : 为元素添加样式类.
    • element.classList.remove(样式类名) : 为元素移除样式类.
    • element.classList.toggle(样式类名) : 为元素以开关的方式增加/移除样式类.
    • element.classList.replace(旧样式类名, 新样式类名) : 为元素把旧样式替换成新样式, 若没有旧样式, 则直接添加新样式.
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>className和classList操作class属性值</title>
  7. <style>
  8. .red {
  9. color: red;
  10. }
  11. .bgc {
  12. background-color: yellow;
  13. }
  14. .blue {
  15. color: blue;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <p class="red">hello JavaScript!</p>
  21. <h3>hello JS!</h3>
  22. <script>
  23. var cl = console.log.bind(console);
  24. var p = document.querySelector("p");
  25. // 获取<p>的class属性, 注意, class是js是保留字, 不能用, 所以用className代替
  26. cl(p.clasName);
  27. // 1. 使用className属性操作元素样式类
  28. // 样式类(增,删,替换等)
  29. p.className = "bgc";
  30. p.className = "red bgc";
  31. // 上面的方式很麻烦, 使用classList对象就容易操作了
  32. var h3 = document.querySelector("h3");
  33. // 2. 使用classList属性操作元素样式类
  34. // 为元素添加样式类
  35. h3.classList.add("red");
  36. h3.classList.add("bgc");
  37. // 移除元素的样式类
  38. h3.classList.remove("bgc");
  39. // 自动切换, 即当前如果有某个样式类, 则删除该样式类, 没有, 则添加该样式类
  40. h3.classList.toggle("red");
  41. // 替换样式类replace(旧样式类, 新样式类)
  42. h3.classList.replace("bgc", "red");
  43. </script>
  44. </body>
  45. </html>

5. 使用 dataset 对象处理用户自定义的数据属性

  • 用户可以在元素中定义自定义的数据属性, 格式是属性名以 data- 为前缀. 如: data-id , data-username 等.
  • 获取用户自定义数据属性的方式: element.dataset.去掉前缀的自定义属性名 .
    • 如果自定义的属性名是两个单词用短横线相连, 则转为小驼峰命名. 如: data-user-name , 获取时: element.dataset.userName .
  • 赋值: element.dataset.去掉前缀的自定义属性名 = 新值 .
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>dataset对象:用于处理用户自定义的数据属性</title>
  7. </head>
  8. <body>
  9. <!-- html5中, 可以使用自定义的数据属性保存标签的附加信息, 以"data-"为前缀 -->
  10. <div id="user" data-id="1" data-user-name="zhangsan" data-email="zs@qq.com">用户信息</div>
  11. <script>
  12. var cl = console.log.bind(console);
  13. // 获取元素
  14. var user = document.querySelector('div');
  15. // 1. 获取自定义属性值
  16. // dataset对象用于获取用户自定义的数据属性。使用方法:dataset(去掉"data-"前缀的数据属性名)
  17. cl(user.dataset.id);
  18. cl(user.dataset.email);
  19. // 多单词属性,把中间连接线删除,第二个单词字母大写,形成驼峰命名
  20. cl(user.dataset.userName);
  21. // 2. 设置自定义属性值
  22. // 同样也可以用dataset设置用户自定义数据属性的值
  23. user.dataset.email = 'zhangsan@qq.com';
  24. cl(user.dataset.email);
  25. </script>
  26. </body>
  27. </html>

6. 为元素添加事件处理脚本

6.1 使用元素的 onxxx 属性添加

js常用的事件: https://www.cnblogs.com/theblogs/p/9972319.html

以添加点击事件为例:

  • 添加 onclick 属性: <button onclick="...">提交</button>
  • onclick 属性的值可以是调用 js 函数的表达式, 也可以是其他 js 表达式.
  • 也可以在 js 脚本中添加: button.onclick = function(event) {...} .

6.2 使用监听器的方式添加

  • 为元素添加事件监听的方法是: element.addEventListener(事件类型, 回调函数, 事件传递机制) . 事件传递机制见第7点.
  • 监听器可以认为是一个内部方法, 几乎所有元素都有.
  • 事件传递机制有捕获(参数值为 true)和冒泡(参数值为 false).

6.3 事件派发(使用代码触发事件)

  • 一般的事件都由用户主动触发, 如用户点击, 用户移动鼠标进入区域等. 可以用事件派发的方式, 由代码来触发事件.
  • 事件派发的使用场景之一: 轮播图.
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>事件添加方式</title>
  7. </head>
  8. <body>
  9. <!-- 方式1: onclick属性指定处理的js函数或表达式 -->
  10. <!-- 1.1: 直接写js代码 -->
  11. <button onclick="var text=this.innerText;alert(text);">按钮1</button>
  12. <!-- 1.2: 调用js函数 -->
  13. <button onclick="show(this)">按钮2</button>
  14. <!-- 方式2: 给html元素添加属性 -->
  15. <button>按钮3</button>
  16. <!-- 方式3: 监听器方式 -->
  17. <button>按钮4</button>
  18. <!-- 方式4: 事件派发 -->
  19. <button>按钮5</button>
  20. </body>
  21. <script>
  22. // 给console.log起别名
  23. var cl = console.log.bind(console);
  24. /* 方式1.2 */
  25. function show(element) {
  26. var text = element.innerText;
  27. alert(text);
  28. }
  29. /* 方式2: 给html元素添加onclick属性 */
  30. var btn3 = document.querySelector('button:nth-of-type(3)');
  31. btn3.onclick = function() {
  32. alert(this.nodeName);
  33. }
  34. /* 方式3: 监听器方式 */
  35. // 监听器可以认为是一个内部方法, 几乎所有元素都有. element.addEventListener(事件类型, 事件回调函数, 传递机制);
  36. // 其中传递机制有两种, 一种是捕获(值为true), 一种是冒泡(值为false), 即: 冒泡阶段触发. 见demo7.html
  37. var btn4 = document.querySelector('button:nth-of-type(4)');
  38. btn4.addEventListener('click', function(){
  39. alert(this.innerText);
  40. }, false);
  41. /* 方式4: 事件派发(可以模拟自动触发, 而不需要用户点击触发) */
  42. // 先给按钮5添加一个点击事件
  43. var btn5 = document.querySelector('button:nth-of-type(5)');
  44. btn5.addEventListener('click', function(){
  45. console.log(this.innerText);
  46. }, false);
  47. // 创建一个点击事件对象
  48. var event = new Event('click');
  49. // 派发给btn5(执行派发语句后, 立刻触发btn5的点击事件,不用用户点击)
  50. btn5.dispatchEvent(event);
  51. // 事件派发使用场景: 轮播图
  52. </script>
  53. </html>

7. 事件传递机制

  • 事件传递机制有两种: 捕获冒泡.

    • 捕获是由长辈元素向后辈元素传递事件触发. 从最大的长辈元素(即, 根元素 <html> )开始, 一直传递到事件触发的最小后辈元素为止. 事件触发传递到的元素上绑定有事件对应的处理脚本的, 则执行事件处理脚本.
    • 冒泡是有最小触发事件的元素向长辈元素方向传递事件触发. 一直传递到最大的长辈元素(即, 根元素 <html> )为止. 事件触发传递到的元素上绑定有事件对应的处理脚本的, 则执行事件处理脚本.

事件传递之捕获:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>事件传递之捕获</title>
  7. <style>
  8. .first {
  9. padding: 30px;
  10. background-color: yellow;
  11. }
  12. .second {
  13. padding: 30px;
  14. background-color: red;
  15. }
  16. .third {
  17. width: 100px;
  18. height: 100px;
  19. background-color: lightgreen;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="first">
  25. <div class="second">
  26. <div class="third">事件传递</div>
  27. </div>
  28. </div>
  29. </body>
  30. <script>
  31. var cl = console.log.bind(console);
  32. // 事件捕获与冒泡(两种处理父子元素之间事件传递的方式)
  33. // 当最内层元素节点被点击时, 认为是从最外层元素节点, 向最内层元素节点传递事件, 最后由最内层元素节点触发事件. 这个由外向内传递事件的过程叫捕获
  34. // 当最内层元素节点被点击时, 认为是从最内层元素节点, 向最外层元素节点传递事件, 最后由最外层元素节点触发事件. 这个由内向外传递事件的过程叫冒泡
  35. var first = document.querySelector('.first');
  36. var second = document.querySelector('.second');
  37. var third = document.querySelector('.third');
  38. // 根元素添加点击事件
  39. document.documentElement.addEventListener('click', function (ev) {
  40. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);
  41. }, true);
  42. // body元素添加点击事件
  43. document.body.addEventListener('click', function (ev) {
  44. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);
  45. }, true);
  46. // addEventListener()第三个入参值为true,表示捕获阶段触发事件.
  47. first.addEventListener('click', function (ev) {
  48. // ev:事件对象(Event),可以通过它了解很多事件信息
  49. // 事件类型(是点击,还是双击,等等)
  50. cl(ev.type);
  51. // 触发事件的元素
  52. cl(ev.target);
  53. // 绑定事件的元素
  54. cl(ev.currentTarget);
  55. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);
  56. }, true);
  57. second.addEventListener('click', function (ev) {
  58. // ev:事件对象(Event),可以通过它了解很多事件信息
  59. // 事件类型(是点击,还是双击,等等)
  60. cl(ev.type);
  61. // 触发事件的元素
  62. cl(ev.target);
  63. // 绑定事件的元素
  64. cl(ev.currentTarget);
  65. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);
  66. }, true);
  67. third.addEventListener('click', function (ev) {
  68. // ev:事件对象(Event),可以通过它了解很多事件信息
  69. // 事件类型(是点击,还是双击,等等)
  70. cl(ev.type);
  71. // 触发事件的元素
  72. cl(ev.target);
  73. // 绑定事件的元素
  74. cl(ev.currentTarget);
  75. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);
  76. }, true);
  77. </script>
  78. </html>

事件传递之冒泡:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>事件传递之冒泡</title>
  7. <style>
  8. .first {
  9. padding: 30px;
  10. background-color: yellow;
  11. }
  12. .second {
  13. padding: 30px;
  14. background-color: red;
  15. }
  16. .third {
  17. width: 100px;
  18. height: 100px;
  19. background-color: lightgreen;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="first">
  25. <div class="second">
  26. <div class="third">事件传递</div>
  27. </div>
  28. </div>
  29. </body>
  30. <script>
  31. var cl = console.log.bind(console);
  32. // 事件捕获与冒泡(两种处理父子元素之间事件传递的方式)
  33. // 当最内层元素节点被点击时, 认为是从最外层元素节点, 向最内层元素节点传递事件, 最后由最内层元素节点触发事件. 这个由外向内传递事件的过程叫捕获
  34. // 当最内层元素节点被点击时, 认为是从最内层元素节点, 向最外层元素节点传递事件, 最后由最外层元素节点触发事件. 这个由内向外传递事件的过程叫冒泡
  35. var first = document.querySelector('.first');
  36. var second = document.querySelector('.second');
  37. var third = document.querySelector('.third');
  38. // 根元素添加点击事件
  39. document.documentElement.addEventListener('click', function (ev) {
  40. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);
  41. }, false);
  42. // body元素添加点击事件
  43. document.body.addEventListener('click', function (ev) {
  44. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);
  45. }, false);
  46. // addEventListener()第三个入参值为false,表示冒泡阶段触发事件. 目前冒泡是更流行的事件传递方式
  47. first.addEventListener('click', function(ev){
  48. // ev:事件对象(Event),可以通过它了解很多事件信息
  49. // 事件类型(是点击,还是双击,等等)
  50. cl(ev.type);
  51. // 触发事件的元素
  52. cl(ev.target);
  53. // 绑定事件的元素
  54. cl(ev.currentTarget);
  55. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);
  56. }, false);
  57. second.addEventListener('click', function(ev){
  58. // ev:事件对象(Event),可以通过它了解很多事件信息
  59. // 事件类型(是点击,还是双击,等等)
  60. cl(ev.type);
  61. // 触发事件的元素
  62. cl(ev.target);
  63. // 绑定事件的元素
  64. cl(ev.currentTarget);
  65. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);
  66. }, false);
  67. third.addEventListener('click', function(ev){
  68. // ev:事件对象(Event),可以通过它了解很多事件信息
  69. // 事件类型(是点击,还是双击,等等)
  70. cl(ev.type);
  71. // 触发事件的元素
  72. cl(ev.target);
  73. // 绑定事件的元素
  74. cl(ev.currentTarget);
  75. cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);
  76. }, false);
  77. </script>
  78. </html>

8. 利用事件冒泡实现事件委托/代理

  • 应用场景和实现原理: 当需要为多个元素添加相同的事件处理脚本时, 可以把事件处理脚本绑定到这些元素共同的长辈元素上, 通过事件冒泡, 委托长辈元素执行事件处理脚本.
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>冒泡实现事件委托案例</title>
  7. <style>
  8. .item {
  9. height: 32px;
  10. margin: 10px;
  11. background-color: #f1f1f1;
  12. }
  13. </style>
  14. </head>
  15. <body>
  16. <span>当某个元素中的多个子元素都拥有某个相同的事件时, 如果要为每个子元素添加事件, 会很麻烦, 使用事件委托, 即, 把事件绑定到父元素上, 通过冒泡的方式, 把事件传递到父元素上的同名事件上触发</span>
  17. <ul>
  18. <li class="item">item1</li>
  19. <li class="item">item2</li>
  20. <li class="item">item3</li>
  21. <li class="item">item4</li>
  22. <li class="item">item5</li>
  23. </ul>
  24. <script>
  25. // 给console.log方法取别名
  26. var cl = console.log.bind(console);
  27. // 获取父元素
  28. var ul = document.querySelector('ul')
  29. // 事件绑定在父元素上
  30. ul.addEventListener('click', function(e) {
  31. // 在事件回调函数中, this===e.target, 即触发事件的元素.
  32. cl(e.target.innerText + '被点击了, 但是它没有绑定点击处理函数, 所以它执行的是绑定在' + e.currentTarget.nodeName + '上的事件处理方法');
  33. }, false);
  34. </script>
  35. </body>
  36. </html>

学习心得

  • NodeList和HTMLCollection的区别: 前者有forEach方法, 后者没有. 其他的, 如像数组一样访问元素的方式, item(index) 方法, length 属性, 元素键名从0开始, nameItem(name属性值) 方法 等, 二者都有.

  • 在 JS 中, 节点类型共有 11 种, 跟 HTML 相关的有 6 种(其他 5 种和 XML 相关), 元素节点只是其中之一.

  • 事件的添加方式有: 1. 为元素添加”on事件名”属性; 2. 在js脚本中, 以”元素.on事件名=匿名函数”的方式添加; 3. 使用监听器( addEventListener(事件名, 回调函数, 传递机制) )的方式添加.

  • 当需要为多个元素添加相同的事件处理脚本时, 可以把事件处理脚本绑定到这些元素共同的长辈元素上, 通过事件冒泡, 委托长辈元素执行事件处理脚本.

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议