js 事件与 fetch api 简单总结
js 运行机制
- 同步任务:单线程(主线程)
js 是单线程运行,只有一个主线程,同一时刻只能执行一个代码,没有 c++、java 等的并行运行,单线程的任务只能一个个的执行,且执行顺序跟随用户的代码书写顺序。
console.log(1);
console.log(2);
console.log(3);
- 异步任务(事件循环与任务队列)
当 js 运行时遇到延时任务或耗时任务,js 引擎会自动将该任务离开主线程,将其加入到任务队列中,在所有主线程任务执行完毕后,由时间循环将该任务重新放回主线程开始执行。
console.log(1);
// 设置定时任务,延时3秒后输出
setTimeout(() => console.log(2), 3000);
console.log(3);
异步任务类型及解决
类型:- 定时任务
- 事件
- IO 操作(input 与 output),包括本地和远程
- 网络请求 http 请求
解决:
异步任务可以使用回调函数来实现异步回调,既保证了页面非延时数据能不被阻塞的显示出来,又保证位置能在原来的位置。
事件
事件的添加、删除与派发
事件的添加的三种方式
事件属性直接添加
<button onclick="alert('hello')">事件属性</button>
获取元素对象添加
<button id="btn">元素对象</button>
<script>
const btn = document.querySelector("#btn");
btn.onclick = () => console.log("111");
</script>
事件监听器添加(事件监听器添加的会都输出出来)
<button id="btn">事件监听器</button>
<script>
const btn = document.querySelector("#btn");
btn.addEventListener("click", () => console.log("111"));
btn.addEventListener("click", () => console.log("222"));
btn.addEventListener("click", () => console.log("333"));
</script>
事件删除
- 行内事件属性添加的事件从 html 代码中删除即可
- 元素对象可以给 onclick 事件赋值一个 null 清空值
<button id="btn">元素对象</button>
<script>
const btn = document.querySelector("#btn");
btn.onclick = () => console.log("111");
btn.onclick = null;
</script>
- 事件监听器可以将事件回调函数提前赋值给一个变量,使用:元素.addEventListener(事件类型,事件回调函数变量名,是否冒泡)来添加,使用元素.removeEventListener(事件类型,事件回调函数变量名,是否冒泡)来删除
<button id="btn">事件监听器</button>
<script>
const btn = document.querySelector("#btn");
const test = () => console.log("111");
btn.addEventListener("click", test);
btn.removeEventListener("click", test);
</script>
事件派发
事件派发可以自动模拟派发执行一个事件,创建好事件监听执行后,使用:new Event(“事件名”)创建一个自定义事件,然后使用:元素.dispatchEvent(创建好的自定义事件)派发任务。
<button id="btn">事件派发</button>
<script>
//获取按钮
const btn = document.querySelector("#btn");
//给一个变量赋值,用在后面循环中
let i = 0;
//创建点击事件的执行内容,设置的变量自增+0.5
btn.addEventListener("click", () => {
console.log("已经扛了" + i + "吨砖");
i += 0.5;
});
//创建自定义点击事件
const myClick = new Event("click");
//使用btn.dispatchEvent(myClick)派发任务
setInterval(() => btn.dispatchEvent(myClick), 1000);
</script>
事件冒泡
- 事件对象,如
<button onclick="show(event)">click</button>
,函数 show 里面的(event)实参是一个固定值,只有 event 实参代表事件对象 - 由于 event 是对象,他就有对应的一些如 type 之类的属性,但是其中有两个非常重要的属性:事件绑定者(主体)event.currentTarget、事件触发者(目标)event.target
- 事件冒泡:onclick 这种通过事件属性添加的事件是冒泡事件,所谓冒泡事件就是如果父元素有子元素的同名事件,会沿着 dom 树向上逐级触发上级元素的同名事件
- 事件委托:例如现在有一个无序列表,里面存在 100 个 li,我们想设置,点击每个 li 触发背景色产生一个变化,如果给 100 个 li 循环遍历或者一次添加点击事件就非常麻烦,但是我们利用事件冒泡的原理,只给父元素添加一个点击事件,就可以实现这个问题,这里因为 100 个 li 会显得太多,先以 10 个为例,设置点击后给 ul 添加一个背景色,然后先循环给所有 li 加 ul 的背景色,点击哪个 li,哪个 li 变色
<ul onclick="changeColor(event)">
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
<li>item9</li>
<li>item10</li>
</ul>
<script>
const lis = document.querySelectorAll("ul>li");
function changeColor(ev) {
for (let i = 0; i < lis.length; i++) {
const li = lis[i];
lis[i].style.backgroundColor = "lightgreen";
}
ev.target.style.backgroundColor = "hotpink";
ev.currentTarget.style.backgroundColor = "lightgreen";
}
</script>
fetch api
使用 fetch api 进行异步请求,fetch(“链接地址”)获取到的是一个流格式数据,需要使用 fetch(“url”).then(响应回调函数).then(结果处理)来把流格式的数据转为 json。
fetch(“url”).then(响应回调函数).then(结果处理)链式调用:
fetch("data.json").then((response) => response.json().then((json) => console.log(json)));
下面用接口做个简单的表格输出案例,获取 id 跟 title 输出到表格中:
<!DOCTYPE html>
<html lang="zh-CN">
<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>fetch api</title>
<style>
th,
td {
border: 1px solid;
}
table {
border-collapse: collapse;
}
caption {
font-weight: bolder;
}
</style>
</head>
<body>
<table>
<caption>
信息表
</caption>
<thead>
<tr>
<th>id</th>
<th>标题</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
//获取tbody准备后续动态填充内容
const tbody = document.querySelector("table>tbody");
//异步回调函数,调取接口数据
async function data() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts");
const comments = await response.json();
// console.log(comments);
// count函数中处理数据
count(comments);
}
data();
function count(comment) {
// 对获取到的数据循环遍历
comment.forEach((item) => {
//创建一行两列
const tr = document.createElement("tr");
const iTd = document.createElement("td");
const tTd = document.createElement("td");
//给单元格填充内容并添加到表格中
iTd.textContent = item["id"];
tTd.textContent = item["title"];
tr.append(iTd, tTd);
tbody.append(tr);
});
}
</script>
</body>
</html>