web API (04)
事件对象
获取事件对象
- 事件对象是什么
- 也是个对象,这个对象里有事件触发时的相关信息
- 列如: 鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
- 获取
- 在事件绑定的回调函数的第一个参数就是事件对象
- 一般命名为 event 、 e 、 ev
<script>
const bnt = document.querySelector('button')
bnt.addEventListener('click',function (event) {
console.log(event); // 存放事件触发一瞬间的信息 - 鼠标位置信息
})
</script>
事件对象常用属性
- 部分常用属性
- type
- 获取当前的事件类型
- clientX / clientY
- 获取光标相对于浏览器可见窗口左上角的位置
- offsetX / offsetY
- 获取光标相对于当前Dom元素左上角的位置
- type
<script>
const div = document.querySelector('div')
// 鼠标移动动
div.addEventListener('mousemove',function (event) {
// console.log(event.type); // 输出当前的事件类型 少用
// console.log(event.clientX,event.clientY); // 反回 鼠标的位置 - 参照物 页面的左上角即
console.log(event.offsetX,event.offsetY); // 返回鼠标的坐标, 参照物 是被点击的元素的左上角
})
</script>
跟随鼠标移动案例
-
需求:一张图片一直跟着鼠标移动
分析:
①:鼠标在页面中移动,用到 mousemove 事件
②:不断把鼠标在页面中的坐标位置给图片left和top值即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>04-小鸟跟随鼠标.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* div {
width: 100px;
height: 100px;
background-color: aqua;
position: fixed;
} */
img {
position: fixed;
/* width: 50px; */
/* 移动自身宽度和高度的一半 */
transform: translate(-50%, -50%);
}
body {
height: 100vh;
/* 隐藏鼠标 */
cursor: none;
}
</style>
</head>
<body>
<h1>用户鼠标不要移动那么快</h1>
<!-- <div></div> -->
<img src="./images/xn.png" alt="" />
<script>
/*
1 给body标签 绑定 鼠标移动事件
body也是一个普通的块级元素 高度由内容撑开 同时 div使用了定位-脱标 body标签没有高度
2 事件触发了 获取 事件对象的坐标 clientX
3 把坐标设置给div的left top
*/
// const div = document.querySelector('div');
const img = document.querySelector('img');
document.body.addEventListener('mousemove', function (event) {
const left = event.clientX;
const top = event.clientY;
img.style.left = left + 'px';
img.style.top = top + 'px';
});
</script>
</body>
</html>
键盘案键
<script>
// 给body标签 绑定 键盘按下事件 keydown
document.body.addEventListener('keydown', function (event) {
console.log(event.key);// 当下按下的按键 !
});
</script>
案例
-
需求:按下回车键盘,可以发布信息
分析:
①:用到按下键盘事件 keydown 或者 keyup 都可以
②:如果用户按下的是回车键盘,则发布信息
③:按下键盘发布新闻,其实和点击发布按钮效果一致 send.click()
<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>
<textarea id="ttx"></textarea>
<button>发布</button>
<ul></ul>
<script>
let ttx = document.querySelector('#ttx')
let bnt = document.querySelector('button')
let ul = document.querySelector('ul')
// 给按钮标签设置点击事件
bnt.addEventListener('click',function () {
// 点击发布的时候添加一个li标签
let li = document.createElement('li')
// 让文本的内容等于 li 里面的内容
li.innerText = ttx.value
ul.appendChild(li)
// 点击发布的时候 文本里面的内容等于空字符串
ttx.value = ''
})
document.body .addEventListener('keydown',function (event) {
console.log(event.key);
// 给按钮绑定过点击事件,点击事件也是可以主动触发
if(event.key === 'Enter'){
bnt.click()// 相当于你点击了一下按钮
}
})
</script>
</body>
</html>
事件流
事件流和两个阶段说明
- 事件流指的是事件完整执行过程中的流动路径
- 说明 , 假设页面里有个div ,当触发事件时,会经历两个阶段 ,分别是捕获阶段 ,冒泡阶段
- 捕获阶段是从父到子
- 冒泡阶段是从子到父
事件捕获和冒泡
-
事件流动
-
给多个父子结构的标签绑定事件,先点击了子元素,产生事件流动
-
事件流动 分成了两个阶段
- 捕获阶段 父节点 流动到子节点
- 冒泡节点 子节点 流动到父节点 默认
- 事件流动方向 默认是 使用了冒泡 - 点击儿子标签 触发 儿子 - 父亲 - 爷爷
-
我们可以修改触发事件 让它选择使用 捕获阶段还是冒泡阶段
-
addEventListener 可以选择使用冒泡还是捕获
-
addEventListener (事件类型 ,事件处理函数,捕获还是冒泡(默认值 false,可以省略))
<script> const b = document.querySelector('.box') b.addEventListener('click',function () { console.log('b'); },true) // 捕获 </script>
-
-
总结
- 捕获和冒泡 特点 了解
- 默认情况 冒泡 如果想要修改 可以 addEventListener 第三个参数传入 true 即可
- 以后代码开发过程中, 还是继续使用默认的 冒泡阶段
-
阻止冒泡
- 在事件对象中 event 找到一个方法 停止冒泡 event.stopPropagation();
b2.addEventListener("click", function (event) {
console.log("b2");
p.innerText = +(p.innerText) +100
p.style.backgroundColor = 'blue'
// 阻止冒泡
event.stopPropagation()
},true);
阻止标签的默认行为
<body>
<a href="http://www.baidu.com">百度</a>
<form >
<!-- <button type="button">点击我 就会自动刷新</button> -->
<!-- <input type="button" value="点击我"> -->
</form>
<button>刷新</button>
<script>
/*
1 a标签的点击跳转
2 form表单中button点击刷新行为
1 阻止默认行为 - form表单 有一个 submit 事件 理解提交表单的触发-点击按钮的时候触发
2 给button按钮绑定点击事件 也去阻止试试
3 给button按钮 添加一个 type="button" 属性
4 换成 input标签 type="button"
5 把button 移出form表单的区域
使用新技术 阻止标签默认行为
*/
const a=document.querySelector("a");
const form=document.querySelector("form");
const button=document.querySelector("button");
a.addEventListener("click",function (event) {
console.log("a标签的点击触发啦");
// 阻止a标签的默认行为,让他不要跳转
event.preventDefault();
})
// form.addEventListener("submit",function (event) {
// // 不要让页面再刷新
// event.preventDefault();
// })
// button.addEventListener("click",function (event) {
// event.preventDefault(); // 不要让页面再刷新
// })
</script>
事件委托感受
- 优点 : 给父级元素加事件(可以提高性能)
- 原理 : 事件委托其实是利用事件冒泡的特点 ,给父元素添加事件,子元素可以触发
- 实现 : 事件对象 . target 可以获得真正触发事件的元素
<script>
// 事件委托
// 本来想要给li标签绑定事件实现业务
// 把事件绑定写在 父元素上 把li标签应该要做的事情 委托给父元素来做!
const ul=document.querySelector("ul");
ul.addEventListener("click",function (event) {
// event.target 有可能是ul标签,有可能是li标签,还有可能是 a标签
// 一会再来解决这个问题。
event.target.style.backgroundColor="red";// 不够完美的
// event.target 你当前点击的是哪个标签(点击最深最底层的那个标签即可)
// console.log(event.target);// 获取到被点击的li标签
})
</script>
事件委托-nodeName
<script>
const ul = document.querySelector('ul');
ul.addEventListener('click', function (event) {
// event.target.style.backgroundColor="red";
// console.log(event.target);
// 只有点击了li标签才触发
// console.log(event.target.nodeName);// 当前点击的元素的标签名 大写
if (event.target.nodeName === 'LI') {
console.log('改变颜色');
event.target.style.backgroundColor = 'red';
}
});
</script>
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>08-综合案例-模版</title>
<style>
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: #721c24;
}
h1 {
text-align: center;
color: #333;
margin: 20px 0;
}
table {
margin: 0 auto;
width: 800px;
border-collapse: collapse;
color: #004085;
}
th {
padding: 10px;
background: #cfe5ff;
font-size: 20px;
font-weight: 400;
}
td,
th {
border: 1px solid #b8daff;
}
td {
padding: 10px;
color: #666;
text-align: center;
font-size: 16px;
}
tbody tr {
background: #fff;
}
tbody tr:hover {
background: #e1ecf8;
}
.info {
width: 900px;
margin: 50px auto;
text-align: center;
}
.info input {
width: 80px;
height: 25px;
outline: none;
border-radius: 5px;
border: 1px solid #b8daff;
padding-left: 5px;
}
.info button {
width: 60px;
height: 25px;
background-color: #004085;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
border-radius: 5px;
}
.info .age {
width: 50px;
}
</style>
</head>
<body>
<h1>新增学员</h1>
<div class="info">
姓名:<input type="text" class="uname" /> 年龄:<input
type="text"
class="age"
/>
性别:
<select name="gender" id="" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:<input type="text" class="salary" /> 就业城市:<select
name="city"
id=""
class="city"
>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</div>
<h1>就业榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- <tr>
<td>1</td>
<td>这是名称</td>
<td>这是年龄</td>
<td>这是性别</td>
<td>这是工资</td>
<td>这是所在城市</td>
<td>
<a href="javascript:" class="del">删除</a>
</td>
</tr> -->
</tbody>
</table>
<script>
let arr = [];
let tbody = document.querySelector("tbody");
// 2 给 录入绑定点击事件
const add = document.querySelector(".add");
const uname = document.querySelector(".uname");
const age = document.querySelector(".age");
const gender = document.querySelector(".gender");
const salary = document.querySelector(".salary");
const city = document.querySelector(".city");
getHtml();
// 根据渲染页面
// 按钮绑定点击事件
add.addEventListener("click", function () {
// 创建一个新的对象 把表单数据都合并到对象中
const data = {
// 学号
id: Date.now(),
// 姓名
uname: uname.value,
// 年龄
age: age.value,
// 性别
gender: gender.value,
// 薪资
salary: salary.value,
// 就业城市
city: city.value,
};
// 打了一个 断点 来验证 上面的代码 没有写错
// 2.2 给数组插入新的元素
arr.push(data);
// 2.3 数组发生改变 重新调用渲染页面的函数
getHtml();
//2.4 表单数据清空
uname.value = "";
age.value = "";
gender.value = "男";
salary.value = "";
city.value = "广州";
});
// 3 tbody 绑定点击事件,同时判断被点击的是不是 del 删除标签
tbody.addEventListener("click", function (event) {
// 判断当前点击的是不是a标签
if (event.target.nodeName === "A") {
// <a data-index="2" href="javascript:" class="del">删除</a>
// 获取到a标签 上存放的 index
// event.target = a标签的dom元素
// console.dir(event.target.dataset.index)
const index = event.target.dataset.num;
// 3.3 执行数组删除元素
arr.splice(index, 1);
// 3.4 调用根据数组渲染页面的函数
getHtml();
}
});
function getHtml() {
let html = ``;
for (let index = 0; index < arr.length; index++) {
html += `<tr>
<td>${arr[index].id}</td>
<td>${arr[index].uname}</td>
<td>${arr[index].age}</td>
<td>${arr[index].gender}</td>
<td>${arr[index].salary}</td>
<td>${arr[index].city}</td>
<td>
<a data-num href="javascript:" class="del">删除</a>
</td>
</tr>`;
}
// 把生成的tr插入到tbody 中
tbody.innerHTML = html;
}
</script>
</body>
</html>
滚动事件和加载事件
滚动事件
- 当页面滚动时触发的事件
- 很多网页需要加测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,返回顶部
- 事件名 : scroll
<script>
const div= document.querySelector('div')
//设置滚动事件
div.addEventListener('scroll',function () {
console.log('你在滚动');
})
</script>
当前滚动距离
- document.documentElement.scrollTop 可以获取当前页面滚动距离
<script>
// 页面级别的滚动
window.addEventListener('scroll',function () {
// 这个代码可以获取当前页面的滚动距离
console.log(document.documentElement.scrollTop);
})
</script>
固定导航栏案例
<!DOCTYPE html>
<html lang="en">
<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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
header {
height: 200px;
background-color: yellow;
}
nav {
height: 200px;
background-color: blue;
}
.flex{
position: fixed;
top: 0px;
left: 0px;
width: 100%;
}
div {
background-color: aqua;
}
body {
height: 100vh;
}
</style>
</head>
<body>
<header></header>
<nav></nav>
<div>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>10</h1>
<h1>11</h1>
<h1>12</h1>
<h1>13</h1>
<h1>14</h1>
<h1>15</h1>
<h1>16</h1>
<h1>17</h1>
<h1>18</h1>
<h1>19</h1>
<h1>20</h1>
<h1>21</h1>
<h1>22</h1>
<h1>23</h1>
<h1>24</h1>
<h1>25</h1>
<h1>26</h1>
<h1>27</h1>
<h1>28</h1>
<h1>29</h1>
<h1>30</h1>
<h1>31</h1>
<h1>32</h1>
<h1>33</h1>
<h1>34</h1>
<h1>35</h1>
<h1>36</h1>
<h1>37</h1>
<h1>38</h1>
<h1>39</h1>
<h1>40</h1>
<h1>41</h1>
<h1>42</h1>
<h1>43</h1>
<h1>44</h1>
<h1>45</h1>
<h1>46</h1>
<h1>47</h1>
<h1>48</h1>
<h1>49</h1>
<h1>50</h1>
<h1>51</h1>
<h1>52</h1>
<h1>53</h1>
<h1>54</h1>
<h1>55</h1>
<h1>56</h1>
<h1>57</h1>
<h1>58</h1>
<h1>59</h1>
<h1>60</h1>
<h1>61</h1>
<h1>62</h1>
<h1>63</h1>
<h1>64</h1>
<h1>65</h1>
<h1>66</h1>
<h1>67</h1>
<h1>68</h1>
<h1>69</h1>
<h1>70</h1>
<h1>71</h1>
<h1>72</h1>
<h1>73</h1>
<h1>74</h1>
<h1>75</h1>
<h1>76</h1>
<h1>77</h1>
<h1>78</h1>
<h1>79</h1>
<h1>80</h1>
<h1>81</h1>
<h1>82</h1>
<h1>83</h1>
<h1>84</h1>
<h1>85</h1>
<h1>86</h1>
<h1>87</h1>
<h1>88</h1>
<h1>89</h1>
<h1>90</h1>
<h1>91</h1>
<h1>92</h1>
<h1>93</h1>
<h1>94</h1>
<h1>95</h1>
<h1>96</h1>
<h1>97</h1>
<h1>98</h1>
<h1>99</h1>
<h1>100</h1>
</div>
<script>
/*
需求: 当页面滚动到一定的高度 nav变成了固定定位
1 一定高度 ??? 其实就是header标签的高 250px
步骤:
1 需要在页面滚动距离 大于或者等于 250 的高时候
1 设置nav标签做一个 固定定位
2 否则就取消固定定位
3 小bug 因为 nav标签做固定定位,不再拥有高度,自然把下面的标签给挡住!!!
解决它
给nav上面的标签 header标签 添加下外边距,大小 等于 nav的高
*/
const nav = document.querySelector('nav')
const header = document.querySelector('header')
window.addEventListener('scroll',function () {
const num = document.documentElement.scrollTop
if (num>=200) {
nav.classList.add('flex')
header.style.marginBottom = 200 + 'px'
}else{
nav.classList.remove('flex')
header.style.marginBottom = 0
}
})
</script>
</body>
</html>
小火箭案例
<!DOCTYPE html>
<html lang="en">
<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 {
height: 8000px;
background-image: linear-gradient(red, blue);
}
div {
/* background-color: yellow; */
position: fixed;
bottom: 20px;
right: 0px;
display: none;
}
a {
background-image: url(./04-小火箭/images/gotop.png);
width: 150px;
height: 195px;
display: inline-block;
}
a:hover {
background-image: url("./04-小火箭/images/gotop.gif");
}
</style>
</head>
<body>
<div class="xxx">
<a href="javascript:;">
<!-- <img src="./04-小火箭/images/gotop.png" alt="" /> -->
</a>
</div>
<script>
const div = document.querySelector("div");
const a = document.querySelector("a");
window.addEventListener("scroll", function () {
const num = document.documentElement.scrollTop;
if (num >= 1000) {
div.style.display = "block";
} else {
div.style.display = "none";
}
});
a.addEventListener("click", function () {
let xxx = setInterval(function () {
let xo =document.documentElement.scrollTop -= 200;
console.log(xo);
if ((document.documentElement.scrollTop === 0)) {
console.log('你好呀');
clearInterval(xxx);
}
}, 100);
});
</script>
</body>
</html>