批改状态:合格
老师批语:留言板用心了
1.1 添加到元素的事件属性上。
<button onclick="console.log(this.innerHTML)">Button1</button>
1.2 通过脚本添加到事件属性上。
<button>Button2</button><script>const btn2 = document.querySelector('body button:nth-of-type(2)');// 添加事件btn2.onclick = () => {console.log(this); // <button></button>console.log(this.innerHTML); // Button2}</script>
这里有一点需要注意的是,onclick不能重复定义一个事件,因为后面的事件会覆盖前面的事件,类似于CSS样式覆盖这个道理。
如果想要移除一个事件,可以使用以下方法:
btn2.onclick = null;
1.3 通过事件监听器添加事件。
addEventListener(事件类型, 事件回调方法, 触发阶段)
<button>Button3</button><script>const btn3 = document.querySelector('button');btn3.addEventerListener('click', function () {console.log(this.innerHTML, '第一次'); // Button3 第一次});btn3.addEventListener('click', function () {console.log(this.innerHTML, "第2次"); // Button3 第二次});</script>
1.3.1事件移除
通过回调函数添加的事件是无法移除的,但是可以通过事件方法函数来移除。
let handle = () => console.log(btn3.innerHTML, "第3次");// 添加点击事件btn3.addEventListener('click', handle); // Button3 第三次// 移除点击事件btn3.removeEventListener('click', handle);
1.3.2事件派发
创建一个按钮,并拿到这个元素:
<button>Button4</button><script>const btn4 = document.querySelector('button');</script>
通过事件派发,结合定时器,我们可以做一个自动点击广告的小案例。
// 创建一个自定义事件let ev = new Event('click');let i = 0;btn4.addEventerListener('click', function () {console.log(`点击了广告,共赚:${i}元`);i += 0.5;});setInterval(btn4.dispatchEvent(ev), 1000);
如果需要理解捕获、目标,冒泡需要先理解什么是事件的对象、事件的绑定者以及事件的触发者,现有如下案例:
以下是定义个一个ul列表的DOM结构:
<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>
给每一个li元素绑定一个点击事件:
const lis = document.querySelectorAll('.item');lis.forEach(li => (li.onclick = ev => {// 事件对象保存着当前事件的所有信息console.log(ev);// 事件类型console.log(ev.type); // click// 事件绑定者console.log(ev.currentTarget);// 事件触发者console.log(ev.target);// 在这种情况下,事件绑定者和触发者都是同一个console.log(ev.currentTarget === ev.target);// 事件的传递路径,假定:点击了item5,此时事件传递的路径就是从内向外逐级传递。console.log(ev.path); // [li.item, ul, body, html, document, Window]}));
注意:on + event事件是不支持捕获的,只支持冒泡:
// 不支持捕获,仅支持冒泡li.onclick = function () {};
addEventListener的第三个参数为true时,表示事件在捕获阶段发生,false在冒泡阶段发生,也是默认事件。
// windowwindow.addEventListener('click', ev => {console.log(ev.currentTarget);}, true);// documentdocument.addEventListener('click', ev => {console.log(ev.currentTarget);}, true);// htmldocument.documentElement.addEventListener('click', ev => {console.log(ev.currentTarget);}, true);// bodydocument.body.addEventListener('click', ev => {console.log(ev.currentTarget);}, true);// uldocument.querySelector("ul").addEventListener('click', ev => {console.log(ev.currentTarget);}, true);

// uldocument.querySelector("ul").addEventListener('click', ev => {console.log(ev.currentTarget);}, false);// bodydocument.body.addEventListener('click', ev => {console.log(ev.currentTarget);}, false);// htmldocument.documentElement.addEventListener('click', ev => {console.log(ev.currentTarget);}, false);// documentdocument.addEventListener('click', ev => {console.log(ev.currentTarget);}, false);// windowwindow.addEventListener('click', ev => {console.log(ev.currentTarget);}, false);

从上述捕获和冒泡两个阶段可以看出来:JavaScript事件触发的三个阶段分别为:捕获阶段、目标阶段、冒泡阶段而这个阶段就是事件的传递机制。
现在如果我不想给每个li元素都添加一个点击事件,只给它的父节点ul添加一个点击事件,那么我应该怎么操作呢?
此时,我们可以统一个li元素的父节点ul添加一个点击事件,然后通过ev.target获取到用户当前操作的元素即可,事件触发者一般是事件绑定者的子元素或后代元素。
document.querySelector('ul').addEventListener('click', ev => {// 事件绑定者console.log(ev.currentTarget);// 事件触发者,一般情况下是事件绑定者的子集console.log(ev.target);});

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>留言板</title><style>{margin: 0;padding: 0;font-size: 10px;box-sizing: border-box;font-family: Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;}ul, li {list-style: none;}.box {width: 50rem;height: 10rem;margin: 1rem auto;}h2 {font-size: 3rem;display: flex;justify-content: center;margin-bottom: 1rem;}#message {display: flex;flex-flow: column nowrap;width: 100%;}#message textarea {width: 100%;min-height: 10rem;padding: .6rem 1rem;border: 1px solid #c9c9c9;border-radius: 2px;outline: none;font-size: 1.4rem;font-family: inherit;}#message .button {width: 100%;height: 5rem;margin-top: 1rem;}#message .button .btn {padding: 0 2rem;height: 3.8rem;border-radius: 3px;border-width: 0;font-size: 1.2rem;outline: none;cursor: pointer;}#message .button .btn:hover {transition: all .3s;opacity: .8;}#message .button .btn.btn-submit {background-color: #3e7771;color: #ffffff;}#message .button .btn.btn-rest {margin-left: .5rem;}#message .content-wrap em.tips {font-style: normal;color: red;margin-top: 1rem;}#list {width: 100%;display: grid;grid-template-columns: 1fr;grid-template-rows: auto;margin-top: 1rem;}#list li {display: grid;grid-template-columns: 4rem 1fr;grid-template-rows: auto auto;gap: .5rem;margin-top: 1rem;}#list li.item .avatar {width: 4rem;height: 4rem;}#list li.item .avatar img {width: 100%;height: 100%;border-radius: 50%;}#list li.item .comment {display: grid;grid-template-columns: 1fr;row-gap: .5rem;}#list li.item .comment .title {display: flex;flex: rows nowrap;align-items: center;}#list li.item .comment .title .nick > * {font-size: 1.6rem;color: #000000;}#list li.item .comment .title .time {color: #8c92a4;margin-left: .5rem;font-size: 1.2rem;color: #8c92a4;font-size: 1.4rem;}#list li.item .comment .context{color: #8c92a4;font-size: 1.2rem;color: #40485B;font-size: 1.4rem;margin: .5rem 0;}#list li.item .del {margin: .5rem 0;display: grid;cursor: pointer;border: none;place-self: center end;grid-area: 2 / 1 / 2 / 3;padding: .5rem;outline: none;}hr {border-color: rgba(222, 222, 222, .5);}</style></head><body><div class="box"><h2>留言板</h2><div id="message"><div class="content-wrap"><textarea class="content" name="message" value="ddd" placeholder="请输入内容"></textarea><em class="tips" style="display: none;">* 留言内容不能为空!</em></div><div class="button"><button class="btn btn-submit">立即提交</button><button type="reset" class="btn btn-rest">重置</input></div></div><hr><ul id="list"></ul></div><script>// 获取元素const msg = document.querySelector('.content');// 提交按钮const btn = document.querySelector('.btn-submit');console.log(btn);// 重置按钮const resetBtn = document.querySelector('.btn-rest');console.log(resetBtn);// 评论列表const ul = document.querySelector('#list');btn.addEventListener('click', ev => {// 获取文本框的内容:msg.valuelet str = ` <li class="item" ><div class="avatar"><img src="data:image/png;base64,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" /></div><div class="comment"><div class="title"><span class="nick"><b>残破的蛋蛋</b></span><div class="time">${formatDate(Date.now())}</div></div><div class="context">${msg.value}</div><hr></div><button class="del" onclick="del(this)">删除</button></li>`;if (msg.value.length === 0) {console.log(1);document.getElementsByClassName('tips')[0].style.display = 'block';return false;}ul.insertAdjacentHTML('afterbegin', str);msg.value = '';});// 删除评论function del(element) {confirm('确定要删除这条评论吗?') ? element.parentNode.outerHTML = null : false;}// 重置内容resetBtn.onclick = function () {msg.value = '';}// 获取时间function formatDate(time) {let date = new Date(time);console.log(date);let y = date.getFullYear();console.log(y);let m = date.getMonth();m = date.getMonth()+1 < 10 ? `0${date.getMonth()+1}` : date.getMonth()+1console.log(m);let d = date.getDate();console.log(d);let h = date.getHours();console.log(h);let i = date.getMinutes();console.log(i);let s = date.getSeconds();console.log(s);return `${y}-${m}-${d} ${h}-${i}-${s}`;}</script></body></html>

// 1. concat() 拼接字符串let str = "html".concat(" css ", "php !", 888);console.log(str); // html css php !888// 2. slice(start, end) 取子串str = "html css php !";let res = str.slice(0, 5);console.log(res); // html// 省略第二个参数,表示从0一直取到末尾res = str.slice(0);console.log(res); // html css php !res = str.slice(5);console.log(res); // html css php !res = str.slice(-5);console.log(res); // html css php !res = str.slice(-5, -2);console.log(res); // html css php !// 3.substr(start, length)res = str.substr(0, 6);console.log(res);res = str.substr(-5, 3);console.log(res);// 4.trim():删除两端空格let pwd = " root888 ";console.log(pwd.length); // 13// 5.将字符串打成数组res = str.split("");console.log(res);// 比如说从邮箱中解析出用户和邮箱地址res = "admin@admin.cn".split("@");console.log(res[0]); // adminconsole.log(res[1]); // admin.cn// 6.查找字符串中的字符串str = "The full name of China is the People's Republic of China.";// 使用indexof()方法返回字符串指定的文本首次出现的位置console.log(str.indexOf('China')); // 17// lastIndexOf()方法返回指定的字符串在文本中最后一次出现的位置console.log(str.lastIndexOf('the')); // 26// indexof()和lastIndexOf()如果在文中本找到指定的字符串,则返回-1console.log(str.indexOf('hello')); // -1console.log(str.lastIndexOf('hello')); // -1// 7.search()方法返回指定文本在文中第一次出现的位置str = "The full name of China is the People's Republic of China.";console.log(str.search('China')); // 17// 8.替换字符串str = "Please visit microsoft and Microsoft!";console.log(str.replace('Microsoft', '微软')); // Please visit microsoft and 微软!// 默认的replace()只替换首次匹配的字符串,并且对大小写敏感// 9.大小写转换str = 'Hello World!';// 字符串转大写console.log(str.toUpperCase()); // HELLO WORLD!console.log(str.toLocaleUpperCase()); // HELLO WORLD!// 字符串转小写console.log(str.toLowerCase()); // hello world!console.log(str.toLocaleLowerCase()); // hello world!// 10.charAt()方法返回字符串中指定下标的字符串str = 'Hello World';console.log(str[0]); // H
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号