JS事件和异步
js运行机制:单线程+事件循环
//1、单线程:主线程 //同一时刻,只能执行一段代码 不像c++java 可以并行
//一个任务接一个任务的执行,代码的书写顺序和执行顺序是一致的
console.log(1);
setTimeout(() => console.log(2), 3000);
setTimeout(() => console.log(4), 0);
//定时任务:setTimeout(函数,等待时间)
console.log(3);
//js引擎将第二个任务离开了主线程,放到了任务队列中
//当主线程执行完毕,由事件循环 将定时任务(异步任务)放回
console.log("---------");
// 定时任务就是异步任务,异步任务不在主线程执行
//执行机制
//1、同步任务:主线程
//2、异步任务:任务队列,事件循环来调度
//哪些是异步任务
//1、定时任务 2、事件 3、io操作 4、网络请求(http)
//实现异步 ?回调函数
单线程异步演示
<form action="" style="display: grid; gap: 1em; width: 20em">
<input type="text" onkeydown="console.log(this.value)" />
<input
type="text"
onkeydown="setTimeout(()=>console.log(this.value),0)"
/>
<input type="text" oninput="console.log(this.value)" />
</form>
<!-- 慢半拍 ?dom渲染是同步任务,keydown事件是异步任务 -->
<!-- 解决方案:异步事件等一等,等同步的dom渲染完成再执行 -->
事件增删
<body style="display: grid; gap: 0.5em">
<!-- !1、事件属性 -->
<button onclick="alert('hello')">事件属性</button>
<!-- !!2、元素对象 -->
<button>元素对象</button>
<script>
const btn2 = document.querySelector("button:nth-of-type(2)");
btn2.onclick = () => console.log(111);
btn2.onclick = (_) => console.log(222);
btn2.onclick = ($) => console.log(333);
btn2.onclick = null;
// 覆盖事件
</script>
<!-- 3、事件监听器 -->
<button>事件监听器</button>
<script>
const btn3 = document.querySelector("button:nth-of-type(3)");
//btn3.addEventListener(事件类型,事件回调,是否冒泡false)
btn3.addEventListener("click", () => console.log(111));
btn3.addEventListener("click", () => console.log(222));
btn3.addEventListener("click", () => console.log(333));
let show = () => console.log(444);
btn3.addEventListener("click", show);
//删除
btn3.removeEventListener("click", show);
</script>
<!-- 4、事件派发 -->
<button>事件派发</button>
<script>
const btn4 = document.querySelector("button:nth-of-type(4)");
let i = 0;
btn4.addEventListener("click", () => {
console.log("恭喜又赚了:" + i + "元");
i += 0.5;
});
//创建一个自定义事件
const myclick = new Event("click");
//setTimeout定时任务 setInterval 执行间歇事件
setInterval(() => {
btn4.dispatchEvent(myclick);
}, 3000);
</script>
</body>
事件冒泡和事件委托
<!-- event:事件对象 -->
<button onclick="show(event)">click</button>
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
</ul>
<script>
function show(ev) {
// ev:事件对象
//console.log(ev.type);
//1 事件绑定者(主体)
console.log(ev.currentTarget);
//2 事件触发者
console.log(ev.target);
console.log(ev.currentTarget === ev.target);
}
const lis = document.querySelectorAll("li");
lis.forEach(li => (li.onclick = ev => console.log(ev.currentTarget)));
//冒泡:子元素的同名事件,会沿着dom树向上逐级触发上级元素的同名事件
//document.querySelector("ul").onclick = ev =>
//console.log(ev.currentTarget);
//document.querySelector("body").onclick = ev =>
//console.log(ev.currentTarget);
//document.documentElement.onclick = ev => console.log(ev.currentTarget);
document.querySelector("ul").onclick = ev => {
//1 事件绑定者
//console.log(ev.currentTarget);
//2 事件触发者
console.log(ev.target.textContent);
///console.log(ev.currentTarget === ev.target);
};
</script>
表单事件
<form action="" method="post" id="login" onsubmit="return false">
<label class="title">用户登录</label>
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" value="" autofocus />
<label for="password">密码:</label>
<input type="password" id="password" name="password" />
<button name="submit">登录</button>
</form>
<script>
const login = document.forms.login;
//login.onsubmit = () => console.log("提交了");
//login.onsubmit = ev => ev.preventDefault(); onsubmit="return false"
login.submit.onclick = ev => {
//禁止冒泡
ev.stopPropagation();
//console.log(ev.currentTarget.form);
//非空验证
isEmpty(ev.currentTarget.form);
};
function isEmpty(form) {
console.log(form.email.value.length);
console.log(form.password.value.trim().length);
if (form.email.value.length === 0) {
alert("邮箱不能为空");
form.email.focus();
return false;
} else if (form.password.value.trim().length === 0) {
alert("密码不能为空");
form.password.focus();
return false;
} else {
alert("验证通过");
}
}
//input blur 失去焦点 change 值发生改变时触发 select 触发
</script>
json
//1、json 就是一个字符串
//2、 json用对象或数组的字面量语法,来表示一组相关数据
let josnStr = `
{
"id":12,
"name":"JS是怎么练成的",
"price":99
}
`;
// 1 属性必须是字符串,必须使用双引号
//2、字符串类型必须使用双引号
// 3、最后一个数据后面不能有逗号
// 1、如何用到js中
//(1)json ->js对象
// (2)js对象->渲染到页面中
let book = JSON.parse(josnStr);
console.log(book);
let html = `
<ul>
<li>书号:${book.id}</li>
<li>书名:${book.name}</li>
<li>价格:${book.price} 元</li>
</ul>
`;
document.body.insertAdjacentHTML("afterbegin", html);
//json用到其他编程语言中,如php,java,python go
//js对象->json 字符串 ->由不同的语言的api处理
let obj = { id: 12, name: "JS是怎么练成的", price: 99 };
let str = JSON.stringify(obj);
console.log(str);
Promise Fetch
// let arr = [1, 2, 3];
//pormise 契约 他是一个对象 表示异步操作的结果
//工作中不直接用promise ,而是用fetch api进行异步请求
//console.log(fetch("demo6.heml"));
//语法 fetch(url).then(相应回调函数).then(处理结果)
//console.log(response.json());
fetch("data.json")
.then(response => response.json())
.then(json => console.log(json));
fetch json 实例
<!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 json 实例</title>
</head>
<body>
<!-- async await -->
<button onclick="getPic()">查看图片信息</button>
<div id="box"></div>
<script>
// fetch("https://jsonplaceholder.typicode.com/photos")
// .then(response => response.json())
// .then(json => console.log(json));
async function getPic() {
const pics = await fetch(
"https://jsonplaceholder.typicode.com/photos?albumId=2"
);
const list = await pics.json();
//console.log(list);
//渲染
render(list);
}
// function render(data) {
// const box = document.querySelector("#box");
// const div = document.createElement("div");
// data.forEach(item => {
// //console.log(item);
// const h2 = document.createElement("h2");
// h2.innerHTML = '<a href="' + item.url + '">' + item.title + "</a>";
// const img = document.createElement("div");
// img.innerHTML =
// '<a href="' +
// item.url +
// '"><img src="' +
// item.thumbnailUrl +
// '"></a>';
// div.append(h2);
// div.append(img);
// box.append(div);
// });
// }
//改进
function render(data) {
const box = document.querySelector("#box");
const div = document.createElement("div");
data.forEach(item => {
//console.log(item);
const li = document.createElement("div");
li.innerHTML =
'<div class="lipic"><a href="' +
item.url +
'">' +
item.title +
'</a><a href="' +
item.url +
'"><img src="' +
item.thumbnailUrl +
'"></a></div>';
div.append(li);
box.append(div);
});
}
</script>
<style>
#box div .lipic {
display: grid;
grid-template-columns: 1fr 10rem;
gap: 2em;
}
#box div .lipic a:first-of-type {
color: #333;
line-height: 40px;
text-decoration: none;
}
</style>
</body>
</html>