批改状态:合格
老师批语:图片做得不错, 事件机制是个难点, 其实理解了也非常简单是不是?
forEach 遍历(用 for 遍历). 访问 HTMLCollection 对象的元素的方法:HTMLCollection[index] : 类似数组访问元素的方式.HTMLCollection.item(index) : 通过 HTMLCollection 对象的 item(index) 方法.HTMLCollection.nameItem(元素name属性值) : 通过 HTML Collection 对象的 nameItem() 方法, 传入的参数是要获取的类数组中的元素的 name 属性值.forEach 和 item 方法.NodeList.childNodes[0] .NodeList.item(0) .
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>DOM对象</title></head><body><form action="test1.php"></form><form action="test2.php"></form><form action="test3.php" id='loginForm' name="login"><input type="text" name="username" id="username" value="zhangsan"></form></body><script>// 给console.log()函数绑定一个别名var cl = console.log.bind(console);// 1. 查看当前文档类型, 即<!DOCTYPE html>cl(document.doctype);// 2. 查看根节点, 即<html>元素/* document并不代表根节点, document.documentElement才是 */cl(document.documentElement);// 3. 查看head部分, 即<head>元素cl(document.head);// 4. 查看body部分, 即<body>元素cl(document.body);/* ↑有了document.head和document.body, 就能使用上下级关系访问节点树中的子节点 */// 5. 查看<title>元素/* 方法1: 使用节点树获取 */cl(document.head.title);/* 方法2: 使用document对象的title属性获取 */cl(document.title);// 6. 获取当前HTML文档中的所有表单// 6.1 获取表单对象/* 返回值为: HTMLCollection对象, 类数组, 但并不是数组 *//* 遍历HTMLCollection对象中的元素, 见temp */cl(document.forms);// 6.2 获取表单中的元素/获取HTMLCollection对象中的元素/* 方法1: 采用类似数组的获取方式. ↓获取第2个表单 */cl(document.forms[1]);/* 方法2: 使用HTMLCollection提供的item(元素索引)方法. ↓获取第3个表单 */cl(document.forms.item(2));/* 方法3: 根据元素id获取表单(document.getElementById(id值)可以根据id获取所有元素) */cl(document.getElementById('loginForm'));/* 方法4: 使用HTMLCollection对象提供的nameItem(name属性值)来获取HTMLCollection中的元素 */cl(document.forms.namedItem('login'));// 6.3 获取某个表单中的表单控件的值/* input:text控件: 表单对象.控件的name属性值.value */cl(document.forms.item(2).username.value);</script></html>
通过 document 对象, 利用 HTML 文档元素的树形结构, 可以使用”父级元素. 子级元素”的方式获取 DOM 元素; 也可以使用 document 中提供的一些方法获取到一些固定类型的 DOM 元素, 如: form 元素, title 元素等. 详见 DOM 对象的实例.
还是通过 document 对象提供的方法, 利用元素的属性值来获取 DOM 元素.
document.getElementsByTagName(元素标签名) , 返回值: HTMLCollection 对象; document.getElementById(id值) , 返回值: DOM 元素(Element 对象).document.getElementsByClassName(样式类名) , 返回值: HTMLCollection 对象; document.getElementsByName(name属性值) , 返回值: HTMLCollection 对象; document.querySelector(css选择器表达式) , 返回值: DOM 元素(Element 对象), 若匹配到多个元素, 则返回第一个.document.querySelector(css选择器表达式) , 返回值: 元素数组;
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>获取DOM元素</title></head><body><ul class="list"><li class="item" name="first">item1</li><li class="item" id="item2">item2</li><li class="item active">item3</li><li class="item">item4</li><li class="item" id="item2">item5</li></ul></body><script>var cl = console.log.bind(console);// 2.1 根据标签名来获取元素: `document.getElementsByTagName(元素标签名)`, 返回值: HTMLCollection 对象;/* 获取所有li标签元素 */var lis = document.getElementsByTagName("li");cl(lis);// 2.2 根据 id 属性值来获取元素: `document.getElementById(id值)`, 返回值: DOM 元素(Element 对象)./* 获取id属性值='item2'的元素, 匹配多个也只取1个 */var item2 = document.getElementById("item2");cl(item2);// 2.3 根据样式类来获取元素: `document.getElementsByClassName(样式类名)`, 返回值: HTMLCollection 对象;/* 获取设置有.list样式类的元素 */var ul = document.getElementsByClassName("list");cl(ul);/* 获取同时设置有.item和.active样式类的元素 */var activeItem = document.getElementsByClassName("item active");cl(activeItem);// 2.4 根据 name 属性值来获取元素: `document.getElementsByName(name属性值)`, 返回值: HTMLCollection 对象;/* 获取name属性值为fist的元素, 因返回值是类数组, 所以调用其item(0)方法获取到第一个元素 */var firstItem = document.getElementsByName("first").item(0);cl(firstItem);// 2.5 根据 css 选择器来获取一个元素: `document.querySelector(css选择器表达式)`, 返回值: DOM 元素(Element 对象), 若匹配到多个元素, 则返回第一个./* 获取css选择器表达式是.item匹配到的第一个元素 */var item = document.querySelector(".item");cl(item);// 2.6 根据 css 选择器来获取多个元素: `document.querySelector(css选择器表达式)`, 返回值: **元素数组**;/* 获取css选择器表达式是.item匹配到的所有元素 */var items = document.querySelectorAll(".item");cl(items);/* 获取css选择器表达式是".item:nth-child(-n + 3)"(即前三个)匹配到的所有元素 */var items = document.querySelectorAll(".item:nth-child(-n + 3)");cl(items);/* 遍历这3个元素, 并赋给红色字体样式 */items.forEach(function (item, index, items) {item.style.color = "red";});</script></html>
element.childNodes , 返回类型为 NodeList 类型数据, 取元素值, 跟数组类似, 有 length 属性, 有 forEach 和 item 方法.NodeList.childNodes[0] .NodeList.item(0) .element.nodeType .element.nodeName .element.nodeValue . 只有文本节点才能获得值.element.firstChild .element.lastChild .element.previousSibling .element.nextSibling .
<!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><ul><li>item1</li><li>item2</li><li>item3</li><li>item4</li><li>item5</li></ul></body><script>var cl = console.log.bind(console);// 获取第一个ul元素var ul = document.querySelector("ul");// 1. 获取ul元素的所有类型的子节点var nodes = ul.childNodes;/* 包括5个元素类型节点和6个文本类型节点(回车换行) */cl(nodes);// 2. 遍历ul元素的子节点, 打印其节点属性信息nodes.forEach(function (node, index, nodes) {cl("第",index + 1,"个节点信息: 节点类型: ",node.nodeType,"; 节点名称: ",node.nodeName,"; 节点值: ",node.nodeValue);});// 3. 获取ul元素的第一个子节点cl(ul.firstChild);// 4. 获取ul元素的最后一个子节点cl(ul.lastChild);// 5. 获取ul元素的第5个子节点的上一个节点/下一个节点cl(ul.childNodes.item(6).previousSibling);cl(ul.childNodes.item(6).nextSibling);</script></html>
element.className 以文本的形式返回元素的 class 属性的值.class 属性名也是 js 的保留字, 所以用 className 来获取 class 属性的值.element.classList 提供了很多便捷的操作 class 属性值的方法element.classList.add(样式类名) : 为元素添加样式类.element.classList.remove(样式类名) : 为元素移除样式类.element.classList.toggle(样式类名) : 为元素以开关的方式增加/移除样式类.element.classList.replace(旧样式类名, 新样式类名) : 为元素把旧样式替换成新样式, 若没有旧样式, 则直接添加新样式.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>className和classList操作class属性值</title><style>.red {color: red;}.bgc {background-color: yellow;}.blue {color: blue;}</style></head><body><p class="red">hello JavaScript!</p><h3>hello JS!</h3><script>var cl = console.log.bind(console);var p = document.querySelector("p");// 获取<p>的class属性, 注意, class是js是保留字, 不能用, 所以用className代替cl(p.clasName);// 1. 使用className属性操作元素样式类// 样式类(增,删,替换等)p.className = "bgc";p.className = "red bgc";// 上面的方式很麻烦, 使用classList对象就容易操作了var h3 = document.querySelector("h3");// 2. 使用classList属性操作元素样式类// 为元素添加样式类h3.classList.add("red");h3.classList.add("bgc");// 移除元素的样式类h3.classList.remove("bgc");// 自动切换, 即当前如果有某个样式类, 则删除该样式类, 没有, 则添加该样式类h3.classList.toggle("red");// 替换样式类replace(旧样式类, 新样式类)h3.classList.replace("bgc", "red");</script></body></html>
data- 为前缀. 如: data-id , data-username 等.element.dataset.去掉前缀的自定义属性名 .data-user-name , 获取时: element.dataset.userName .element.dataset.去掉前缀的自定义属性名 = 新值 .
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>dataset对象:用于处理用户自定义的数据属性</title></head><body><!-- html5中, 可以使用自定义的数据属性保存标签的附加信息, 以"data-"为前缀 --><div id="user" data-id="1" data-user-name="zhangsan" data-email="zs@qq.com">用户信息</div><script>var cl = console.log.bind(console);// 获取元素var user = document.querySelector('div');// 1. 获取自定义属性值// dataset对象用于获取用户自定义的数据属性。使用方法:dataset(去掉"data-"前缀的数据属性名)cl(user.dataset.id);cl(user.dataset.email);// 多单词属性,把中间连接线删除,第二个单词字母大写,形成驼峰命名cl(user.dataset.userName);// 2. 设置自定义属性值// 同样也可以用dataset设置用户自定义数据属性的值user.dataset.email = 'zhangsan@qq.com';cl(user.dataset.email);</script></body></html>
js常用的事件: https://www.cnblogs.com/theblogs/p/9972319.html
以添加点击事件为例:
<button onclick="...">提交</button> button.onclick = function(event) {...} .element.addEventListener(事件类型, 回调函数, 事件传递机制) . 事件传递机制见第7点.
<!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><!-- 方式1: onclick属性指定处理的js函数或表达式 --><!-- 1.1: 直接写js代码 --><button onclick="var text=this.innerText;alert(text);">按钮1</button><!-- 1.2: 调用js函数 --><button onclick="show(this)">按钮2</button><!-- 方式2: 给html元素添加属性 --><button>按钮3</button><!-- 方式3: 监听器方式 --><button>按钮4</button><!-- 方式4: 事件派发 --><button>按钮5</button></body><script>// 给console.log起别名var cl = console.log.bind(console);/* 方式1.2 */function show(element) {var text = element.innerText;alert(text);}/* 方式2: 给html元素添加onclick属性 */var btn3 = document.querySelector('button:nth-of-type(3)');btn3.onclick = function() {alert(this.nodeName);}/* 方式3: 监听器方式 */// 监听器可以认为是一个内部方法, 几乎所有元素都有. element.addEventListener(事件类型, 事件回调函数, 传递机制);// 其中传递机制有两种, 一种是捕获(值为true), 一种是冒泡(值为false), 即: 冒泡阶段触发. 见demo7.htmlvar btn4 = document.querySelector('button:nth-of-type(4)');btn4.addEventListener('click', function(){alert(this.innerText);}, false);/* 方式4: 事件派发(可以模拟自动触发, 而不需要用户点击触发) */// 先给按钮5添加一个点击事件var btn5 = document.querySelector('button:nth-of-type(5)');btn5.addEventListener('click', function(){console.log(this.innerText);}, false);// 创建一个点击事件对象var event = new Event('click');// 派发给btn5(执行派发语句后, 立刻触发btn5的点击事件,不用用户点击)btn5.dispatchEvent(event);// 事件派发使用场景: 轮播图</script></html>
事件传递机制有两种: 捕获和冒泡.
<html> )开始, 一直传递到事件触发的最小后辈元素为止. 事件触发传递到的元素上绑定有事件对应的处理脚本的, 则执行事件处理脚本.
<html> )为止. 事件触发传递到的元素上绑定有事件对应的处理脚本的, 则执行事件处理脚本.
事件传递之捕获:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>事件传递之捕获</title><style>.first {padding: 30px;background-color: yellow;}.second {padding: 30px;background-color: red;}.third {width: 100px;height: 100px;background-color: lightgreen;}</style></head><body><div class="first"><div class="second"><div class="third">事件传递</div></div></div></body><script>var cl = console.log.bind(console);// 事件捕获与冒泡(两种处理父子元素之间事件传递的方式)// 当最内层元素节点被点击时, 认为是从最外层元素节点, 向最内层元素节点传递事件, 最后由最内层元素节点触发事件. 这个由外向内传递事件的过程叫捕获// 当最内层元素节点被点击时, 认为是从最内层元素节点, 向最外层元素节点传递事件, 最后由最外层元素节点触发事件. 这个由内向外传递事件的过程叫冒泡var first = document.querySelector('.first');var second = document.querySelector('.second');var third = document.querySelector('.third');// 根元素添加点击事件document.documentElement.addEventListener('click', function (ev) {cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);}, true);// body元素添加点击事件document.body.addEventListener('click', function (ev) {cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);}, true);// addEventListener()第三个入参值为true,表示捕获阶段触发事件.first.addEventListener('click', function (ev) {// ev:事件对象(Event),可以通过它了解很多事件信息// 事件类型(是点击,还是双击,等等)cl(ev.type);// 触发事件的元素cl(ev.target);// 绑定事件的元素cl(ev.currentTarget);cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);}, true);second.addEventListener('click', function (ev) {// ev:事件对象(Event),可以通过它了解很多事件信息// 事件类型(是点击,还是双击,等等)cl(ev.type);// 触发事件的元素cl(ev.target);// 绑定事件的元素cl(ev.currentTarget);cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);}, true);third.addEventListener('click', function (ev) {// ev:事件对象(Event),可以通过它了解很多事件信息// 事件类型(是点击,还是双击,等等)cl(ev.type);// 触发事件的元素cl(ev.target);// 绑定事件的元素cl(ev.currentTarget);cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);}, true);</script></html>
事件传递之冒泡:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>事件传递之冒泡</title><style>.first {padding: 30px;background-color: yellow;}.second {padding: 30px;background-color: red;}.third {width: 100px;height: 100px;background-color: lightgreen;}</style></head><body><div class="first"><div class="second"><div class="third">事件传递</div></div></div></body><script>var cl = console.log.bind(console);// 事件捕获与冒泡(两种处理父子元素之间事件传递的方式)// 当最内层元素节点被点击时, 认为是从最外层元素节点, 向最内层元素节点传递事件, 最后由最内层元素节点触发事件. 这个由外向内传递事件的过程叫捕获// 当最内层元素节点被点击时, 认为是从最内层元素节点, 向最外层元素节点传递事件, 最后由最外层元素节点触发事件. 这个由内向外传递事件的过程叫冒泡var first = document.querySelector('.first');var second = document.querySelector('.second');var third = document.querySelector('.third');// 根元素添加点击事件document.documentElement.addEventListener('click', function (ev) {cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);}, false);// body元素添加点击事件document.body.addEventListener('click', function (ev) {cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.nodeName);}, false);// addEventListener()第三个入参值为false,表示冒泡阶段触发事件. 目前冒泡是更流行的事件传递方式first.addEventListener('click', function(ev){// ev:事件对象(Event),可以通过它了解很多事件信息// 事件类型(是点击,还是双击,等等)cl(ev.type);// 触发事件的元素cl(ev.target);// 绑定事件的元素cl(ev.currentTarget);cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);}, false);second.addEventListener('click', function(ev){// ev:事件对象(Event),可以通过它了解很多事件信息// 事件类型(是点击,还是双击,等等)cl(ev.type);// 触发事件的元素cl(ev.target);// 绑定事件的元素cl(ev.currentTarget);cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);}, false);third.addEventListener('click', function(ev){// ev:事件对象(Event),可以通过它了解很多事件信息// 事件类型(是点击,还是双击,等等)cl(ev.type);// 触发事件的元素cl(ev.target);// 绑定事件的元素cl(ev.currentTarget);cl('捕获阶段:' + '触发元素:' + ev.target.className + ';', '事件绑定的元素:' + ev.currentTarget.className);}, false);</script></html>
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>冒泡实现事件委托案例</title><style>.item {height: 32px;margin: 10px;background-color: #f1f1f1;}</style></head><body><span>当某个元素中的多个子元素都拥有某个相同的事件时, 如果要为每个子元素添加事件, 会很麻烦, 使用事件委托, 即, 把事件绑定到父元素上, 通过冒泡的方式, 把事件传递到父元素上的同名事件上触发</span><ul><li class="item">item1</li><li class="item">item2</li><li class="item">item3</li><li class="item">item4</li><li class="item">item5</li></ul><script>// 给console.log方法取别名var cl = console.log.bind(console);// 获取父元素var ul = document.querySelector('ul')// 事件绑定在父元素上ul.addEventListener('click', function(e) {// 在事件回调函数中, this===e.target, 即触发事件的元素.cl(e.target.innerText + '被点击了, 但是它没有绑定点击处理函数, 所以它执行的是绑定在' + e.currentTarget.nodeName + '上的事件处理方法');}, false);</script></body></html>
NodeList和HTMLCollection的区别: 前者有forEach方法, 后者没有. 其他的, 如像数组一样访问元素的方式, item(index) 方法, length 属性, 元素键名从0开始, nameItem(name属性值) 方法 等, 二者都有.
在 JS 中, 节点类型共有 11 种, 跟 HTML 相关的有 6 种(其他 5 种和 XML 相关), 元素节点只是其中之一.
事件的添加方式有: 1. 为元素添加”on事件名”属性; 2. 在js脚本中, 以”元素.on事件名=匿名函数”的方式添加; 3. 使用监听器( addEventListener(事件名, 回调函数, 传递机制) )的方式添加.
当需要为多个元素添加相同的事件处理脚本时, 可以把事件处理脚本绑定到这些元素共同的长辈元素上, 通过事件冒泡, 委托长辈元素执行事件处理脚本.
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号