博客列表 >JS事件代理的实现机制 (附留言板小案例)

JS事件代理的实现机制 (附留言板小案例)

陈强
陈强原创
2021年01月08日 13:28:12743浏览

事件添加方式

添加到元素的事件属性上

  1. <button onclick="console.log(this.innerHTML)">click</button>

通过脚本添加到事件属性上

  1. <button>点击</button>
  2. <script>
  3. const btn = document.querySelector("button:nth-of-type(2)");
  4. btn.onclick = function () {
  5. console.log(this.innerHTML);
  6. };
  7. </script>
  • 通过脚本的方式添加事件,不能重复定义同一事件,后者会覆盖前者
  • 移除事件 btn.onclick = null;

通过事件监听器添加事件

addEventListener(事件类型,事件回调方法, 触发阶段)

  1. <button>事件监听</button>
  2. <script>
  3. const btn2 = document.querySelector("button:nth-of-type(3)");
  4. btn2.addEventListener("click", function () {
  5. console.log(this.innerHTML);
  6. });
  7. //重复定义click事件
  8. btn2.addEventListener("click", function () {
  9. console.log("重复定义了,但是没问题");
  10. });
  11. </script>

移除事件,通过回调添加的事件是无法移除

  1. const handle = () => console.log("最后一次");
  2. btn2.addEventListener("click", handle);
  3. //移除
  4. btn2.removeEventListener("click", handle);

事件派发小案例

  1. <button>广告收入</button>
  2. <script>
  3. const btn3 = document.querySelector("button:nth-of-type(4)");
  4. //自定义事件 用ev
  5. const ev = new Event("click");
  6. let i = 0;
  7. btn3.addEventListener("click", function () {
  8. console.log("广告被点击了", "挣了", i, "元");
  9. i += 1;
  10. });
  11. //使用间歇式定时器来自动点击广告,1000=1秒
  12. setInterval("btn3.dispatchEvent(ev)", 1000);
  13. </script>

事件传递

捕获: 从最外层元素逐级向内直到事件的绑定者

  • 第三个参数是true表示事件在捕获阶段触发,false是冒泡(默认)
  1. <ul class="list">
  2. <li class="item">item1</li>
  3. <li class="item">item2</li>
  4. <li class="item">item3</li>
  5. <li class="item">item4</li>
  6. </ul>
  7. <script>
  8. const lis = document.querySelectorAll("li");
  9. lis.forEach(
  10. (li) =>
  11. (li.click = (ev) => {
  12. // 事件绑定者
  13. // console.log(ev.currentTarget);
  14. // 事件触发者
  15. // console.log(ev.target);
  16. // 事件传递的路径
  17. // console.log(ev.path);
  18. // 阻止事件冒泡
  19. // ev.stopPropagation();
  20. })
  21. );
  22. //window
  23. window.addEventListener("click", (ev) => console.log(ev.currentTarget), true);
  24. // document
  25. document.addEventListener("click", (ev) => console.log(ev.currentTarget), true);
  26. // html
  27. document.documentElement.addEventListener("click", (ev) => console.log(ev.currentTarget), true);
  28. // body
  29. document.body.addEventListener("click", (ev) => console.log(ev.currentTarget), true);
  30. // ul
  31. document.querySelector("ul").addEventListener("click", (ev) => console.log(ev.currentTarget), true);
  32. </script>

目标: 到达事件目标

冒泡: 从目标再由内向外逐级向上直到最外层元素

  1. // ul
  2. document.querySelector("ul").addEventListener("click",ev=>console.log(ev.currentTarget), false);
  3. // body
  4. document.body.addEventListener("click",ev=>console.log(ev.currentTarget),false);
  5. // html
  6. document.documentElement.addEventListener("click",ev => console.log(ev.currentTarget), false);
  7. // document
  8. document.addEventListener("click",ev=>console.log(ev.currentTarget),false);
  9. // window
  10. window.addEventListener("click",ev=>console.log(ev.currentTarget),false);

事件冒泡与事件代理

  1. // 事件代理: 也叫"事件委托"
  2. const lis = document.querySelectorAll("li");
  3. // 遍历每个li,并逐个为它添加点击事件
  4. // lis.forEach(li=>(li.onclick=ev=>console.log(ev.currentTarget)));
  5. //事件代理方式
  6. document.querySelector("ul").addEventListener("click", ev => {
  7. // 事件绑定者
  8. console.log(ev.currentTarget);
  9. // 事件触发者,通常是"事件绑定者"的子元素
  10. console.log(ev.target);
  11. //查看事件触发者内容
  12. console.log(ev.target.innerHTML);
  13. });

常用表单事件

  • 获取表单
  1. <form action="" method="POST" name="login" id="login">
  2. <label class="title">用户登录</label>
  3. <label for="username">用户名:</label>
  4. <input type="text" name="username" />
  5. <label for="password">密码:</label>
  6. <input type="password" name="userpwd" />
  7. <button name="submit">登录</button>
  8. </form>
  9. <script>
  10. const login = document.forms.namedItem("login");
  11. //去掉默认的提交动作
  12. login.submit.onclick = (ev) => {
  13. ev.preventDefault();
  14. ev.stopPropagation();
  15. //非空验证方法
  16. isEmpty(ev.currentTarget.form);
  17. };
  18. //声明非空方法函数
  19. function isEmpty(form) {
  20. if (form.username.value.length === 0) {
  21. alert("用户名不能为空");
  22. //关闭弹窗后获得焦点
  23. form.username.focus();
  24. return false;
  25. } else if (form.userpwd.value.length === 0) {
  26. alert("密码不能为空");
  27. form.username.focus();
  28. return false;
  29. } else {
  30. alert("登录成功");
  31. }
  32. }
  33. </script>

留言板小案例

  1. <label><input type="text" name="message" /></label>
  2. <ol id="list"></ol>
  3. <script>
  4. // 获取元素
  5. const msg = document.querySelector("input");
  6. const list = document.querySelector("#list");
  7. msg.onkeydown = ev => {
  8. // 键盘事件中,key表示按下的键名
  9. // console.log(ev.key);
  10. if (ev.key === "Enter") {
  11. // 非空判断
  12. if (ev.currentTarget.value.length === 0) {
  13. alert("内容不能为空");
  14. } else {
  15. // 将留言内容添加到列表中
  16. // 创建留言
  17. let str = `<li>${ev.currentTarget.value}</li>`;
  18. // 应该将最新的信息永远放在第一条
  19. list.insertAdjacentHTML("afterbegin", str);
  20. // 清空上一条留言
  21. ev.currentTarget.value = null;
  22. }
  23. }
  24. };
  25. </script>

字符串函数

  • concat()拼装
  1. let str = "html".concat(" css ", "php !");
  • slice(start, end):取子串 按照索引位置计算
  1. str = "hello php.cn";
  2. //从起始位置开始 起始值0
  3. let res = str.slice(0, 5);
  4. console.log(res);
  5. //输出hello
  6. //负数是从结束位置开始 起始值-1
  7. res = str.slice(-6, 9);
  • substr(start, length)
  1. //从0开始,取值长度5
  2. res = str.substr(0, 5);
  • trim():删除二端空格
  1. let psw = " root888 ";
  2. console.log(psw.trim().length);
  • splist将字符串打成数组
  1. res = "admin@php.cn".split("@");
  2. console.log(res[0]);
  3. console.log(res[1]);
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议