常用的两种事件绑定:
DOM0的事件绑定
btn.onclick = function(){}
btn.onclick = function(){} 写多个后面的会把前面的覆盖掉
原因:JS中对象如果有同名属性,后面的肯定会覆盖前面
DOM2的事件绑定:
btn.addEventListener(“click”,funciton(){})
btn.addEventListener(“click”,funciton(){}) 可以写多个监听器
原理:不是基于属性绑定,是基于事件池机制,放到池子中先执行
回调函数:(顾名思义)回头再调用
如果在一个函数中,写了一个函数,里面的函数叫回调函数。
addEventListener()是函数调用,但是你在它里面又写了函数funciton(){}
里面的函数声明,我们叫回调函数
看下面的代码:
window.setTimeout(function(){},1000);
//这里setTimeout()是函数调用,所以里面的function(){}函数声明是回调函数。一部分的回调函数是异步代码:
btn.addEventListener(“click”,funciton(){})
上面的代码中的funciton(){}叫回调函数,它是放到的事件池中问:此函数立即执行了吗?
答:没有
事件池中的函数,只有在合适的时机,才会执行,此处的合适时机指的是事件发生后。问:上面这一行代码的后面的代码会执行吗?
答:肯定会 上面的回调函数我们叫异步代码
浏览器在执行代码时,先会把同步代码执行完毕,然后才会执行异步代码。
JS中的异步任务靠什么实现:
1)回调函数
…
JS是单线程,一次只能执行一个任务:
进程: 工厂 一个项目运行就会产生一个进程 进程和进程这间是彼此独立
有的软件是多进程 有的软件是单进程
单进程:你把这个进程杀死了,这个软件(项目)就进行不了
多进程:一个软件跑起来后,会形成多个进程,典型的就是浏览器
浏览器是多进程 一个选项卡就是一个进程
问:为什么浏览器是多进程的?
答:为了保证一个选项卡挂了,不会影响其它的选项卡
电脑资源:
内存和CPU
线程: 工人 真正干活是的工人
在一个进程中可能有多个线程 JS是单线程
我们的说的JS是单线程是指JS的主线程是单线程的。
任务:同步任何 异步任务 98%都是同步代码 只有个别的是异步代码
log("123");
下面让我们通过一个小项目来实践一下吧!
代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 320px;
height: 170px;
margin: 50px auto;
/* border: 1px solid red; */
}
.box .addBtn {
display: block;
margin: 0 auto;
width: 100px;
height: 30px;
border: 0;
outline: none;
border-radius: 10px;
background-color: skyblue;
color: #fff;
font-weight: bold;
}
.box table {
border: 1px solid gold;
margin: 10px auto;
border-collapse: collapse;
}
.box th,
.box td {
border: 1px solid gold;
width: 80px;
padding: 5px 0;
text-align: center;
}
.box th {
background-color: skyblue;
color: #fff;
}
/* ============== cover =============== */
.cover {
/* 让遮罩层隐藏掉 */
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, .5);
}
.dialog {
/* 默认让dialog 隐藏掉 */
display: none;
/* 如果没有设置参考点,参考点就body */
position: absolute;
/* 由于 dialog 设置了position: absolute; 此时dialog就可以作为参考点 */
top: 50%;
left: 50%;
width: 400px;
height: 260px;
background: #fff;
margin-top: -130px;
margin-left: -200px;
border-radius: 5px;
}
.dialog h3 {
background-color: skyblue;
text-align: center;
height: 35px;
line-height: 35px;
}
.dialog div {
margin: 20px 0 0 20px;
}
.dialog input {
width: 250px;
height: 30px;
border-radius: 3px;
border: 1px solid #ccc;
}
.dialog .comBtn {
display: block;
width: 100px;
height: 30px;
margin: 15px auto 0;
}
.dialog span {
position: absolute;
top: 5px;
right: 8px;
font-size: 20px;
font-weight: bold;
cursor: pointer;
}
</style>
</head>
<body>
<!-- 电影列表 -->
<div class="box">
<button class="addBtn" id="addBtn">添加电影</button>
<table>
<thead>
<tr>
<th>电影名称</th>
<th>领衔主演</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAA</td>
<td>AAA</td>
<!-- href="javascript:;" 用来阻止默认事件的 -->
<td><a href="javascript:;">删除</a></td>
</tr>
<tr>
<td>AAA</td>
<td>AAA</td>
<!-- href="javascript:;" 用来阻止默认事件的 -->
<td><a href="javascript:;">删除</a></td>
</tr>
<tr>
<td>AAA</td>
<td>AAA</td>
<!-- href="javascript:;" 用来阻止默认事件的 -->
<td><a href="javascript:;">删除</a></td>
</tr>
</tbody>
</table>
</div>
<!-- 遮罩层 -->
<div class="cover" id="cover"></div>
<!-- dialog 弹框 -->
<div class="dialog" id="dialog">
<h3>添加电影</h3>
<div>
<label for="moveName">电影名称:</label>
<input type="text" id="moveName" placeholder="请输入电影名称">
</div>
<div>
<label for="star">电影主演:</label>
<input type="text" id="star" placeholder="请输入电影主演">
</div>
<button class="comBtn" id="comBtn">完成</button>
<span class="close" id="close">X</span>
</div>
<!----------------------------部分代码的说明------------------------------>
<!--<script>
var btn = document.getElementById("addBtn");
// 在JS中异步靠回调函数实现
// 以后,你看到一个回调函数,包含这个回调函数的那一片代码就有可能是异步代码
// setTimeout(function(){},1000)
// 下面的事件绑定是异步代码 JS中的异步代码就那几个
// 现在我们就学习一个叫事件绑定
btn.addEventListener("click", function() { // DOM2的事件绑定
})
// 下面的代码我们也叫异步代码,也就是说同步还是异步,指的并不是回调函数
// 指的是事件绑定
btn.onclick = function() {
}
console.log("你看我会执行吗?")
</script>-->
<script>
let btn = document.getElementById("addBtn");
let cover = document.getElementById("cover");
let dialog = document.getElementById("dialog");
let close = document.getElementById("close");
let moveName = document.getElementById("moveName");
let star = document.getElementById("star");
let comBtn = document.getElementById("comBtn");
let as = document.getElementsByTagName("a");
let tbody = document.getElementsByTagName("tbody")[0];
// 点击添加电影按钮,显示遮罩层和模态框
btn.addEventListener("click",function () { // DOM2的事件绑定
cover.style.display = "block";
dialog.style.display = "block";
})
// 点击x,隐藏遮罩层和模态框
close.addEventListener("click",function () {
cover.style.display = "none";
dialog.style.display = "none";
})
// 实现删除(不能实现后来添加的tr的删除)
for (let i = 0; i < as.length; i++) {
// 我们自己给a标签添加了一个事件 已经去掉了默认事件
as[i].addEventListener("click",function () {
// console.log(window.confirm("你确定要删除吗?"));
if(window.confirm("你确定要删除吗?")){
tbody.removeChild(this.parentElement.parentElement)
}
})
}
// 添加电影
comBtn.addEventListener("click",function () {
let str1 = moveName.value.trim();
let str2 = star.value.trim();
// 验证你输入的电影名和主演是否合法 ....
if(str1 && str2){
// 1)创建tr
var tr = document.createElement("tr");
tbody.appendChild(tr);
// 2)创建td
var td1 = document.createElement("td");
td1.innerHTML = str1;
tr.appendChild(td1)
var td2 = document.createElement("td");
td2.innerHTML = str2;
tr.appendChild(td2)
var td3 = document.createElement("td");
// <a href="javascript:;">删除</a>
var a = document.createElement("a");
a.innerHTML = "删除"
a.href = "javascript:;"
// 给a标签的onclick属性赋值 使用addEventListener
a.onclick = function(){
if (window.confirm("你确定要删除吗?")){
tbody.removeChild(this.parentElement.parentElement)
}
}
td3.appendChild(a)
tr.appendChild(td3)
// 3)隐藏遮罩层和模态框
cover.style.display = "none";
dialog.style.display = "none";
}else{
alert("电影名和主演不能为空~")
}
})
</script>
</body>
</html>