事件
什么是事件? 事件是在编程时系统内发生的动作或者发生的事情
比如用户在网页上单击一个按钮
什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件 语法:
注册事件
btn1.addEventListener("事件类型", 处理函数)
事件监听三要素:
事件源: 那个dom元素被事件触发了,要获取dom元素
事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等 事件调用的函数: 要做什么事**
事件监听
演示 鼠标单击与鼠标移入
<button class="btn1">开始</button>
<button class="btn2">退出</button>
<div></div>
<script>
/*
触发事件dom元素 事件类型 事件触发了 做业务 函数
*/
let btn1 = document.querySelector(".btn1")
// 注册事件 语法 : btn1.addEventListener("事件类型", 处理函数)
// click 表示鼠标单击
btn1.addEventListener("click", function(){
console.log("开始抽奖");
})
let btn2 = document.querySelector(".btn2")
btn2.addEventListener("click", function(){
console.log("退出抽奖");
})
let div = document.querySelector("div")
// mouseover 表示 鼠标移入到该区域内
div.addEventListener("mouseover", function(){
console.log("来呀 快活呀");
})
</script>
演示-- 点击数字减少
<button class="btn1">1000</button>
<div></div>
<script>
let btn1 = document.querySelector(".btn1")
let times = 1000
btn1.addEventListener("click", function(){
btn1.value = times
times--
console.log(times);
})
// 方式二
// 获取元素
let button = document.querySelector('button')
// 注册绑定点击事件
button.addEventListener('click', function(){
// 1、获取一下 按钮中的文本
// console.log(button.innerText);
// let num = button.innerText // 数据类型是字符串 比较注意做 + 运算
// console.log(num + 1); // 字符串拼接
// console.log(num - 1); // 隐式转换 转成数字
// button.innerText = button.innerText - 1 // 不用担心变成字符串
// button.innerText = button.innerText + 1 // + 变成字符串
// num = num - 1 // num -= 1 // --num
// button.innerText -= 1
--button.innerText
})
</script>
演示 点击隐藏
<style>
div{
margin: 100px auto;
width: 200px;
height: 200px;
background-color: aqua;
}
</style>
</head>
<body>
<div></div>
<script>
// 点击div 隐藏
let div = document.querySelector('div')
div.addEventListener('click', function(){
div.style.display='none' // 点击 div 隐藏
})
</script>
案例 点击事件---随机点名
<h1></h1>
<button class="btn1">开始随机点名</button>
<button class="btn2">停止点名</button>
<script>
let userName = ['赵云', '诸葛流云', '马云', '小云', '韩菱纱',' 云天舒', '玄霄', '慕容紫英', '紫胤真人']
let h1 = document.querySelector('h1')
let btn1 = document.querySelector('.btn1')
let btn2 = document.querySelector('.btn2')
let timeId
// 方式一
// btn1.addEventListener("click", function(){
// btn1.disabled=true
// timeId = setInterval(function(){
// let index = Math.round(Math.random() * (userName.length - 1))
// h1.innerText = userName[index]
// }, 50)
// })
// btn2.addEventListener("click", function(){
// clearInterval(timeId)
// btn1.disabled=false
// })
// 方式二
function intervalDo(){
let index = Math.round(Math.random() * (userName.length - 1))
h1.innerText = userName[index]
}
btn1.addEventListener("click", function(){
if (timeId !== undefined){
clearInterval(timeId)
}
timeId = setInterval(intervalDo, 100)
})
btn2.addEventListener('click', function () {
// 重新启用 开始按钮
// btn1.disabled = false;
clearInterval(timeId);
});
</script>
事件监听版本
DOM L0
事件源.on事件 = function() { }
DOM L2
事件源.addEventListener(事件, 事件处理函数)
发展史:
DOM L0 :是 DOM 的发展的第一个版本; L:level
DOM L1:DOM级别1 于1998年10月1日成为W3C推荐标准
DOM L2:使用addEventListener注册事件
DOM L3: DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型
演示 (了解)
<!-- 以下两种方式都不推荐 了解即可-->
<!-- <button onclick="console.log(123)" >点击</button> -->
<!-- <button onclick="show()">点击</button> -->
<button class="btn1">点击</button>
<button class="btn2">点击</button>
<script>
// 1 获取dom元素
let btn1 = document.querySelector('.btn1');
let btn2 = document.querySelector('.btn2');
// 使用旧方式 L0 第一个版本的方式绑定点击事件 on+事件类型 = 匿名函数
// on也可以是在 行内 绝对不推荐
btn1.onclick = function () {
console.log('事件触发啦');
};
btn1.onclick = function () {
console.log('事件触发啦');
};
btn1.onclick = function () {
console.log('事件触发啦');
};
// addEventListener 对一个事件类型 绑定多个处理函数
// on+事件 对一个事件类型 只能绑定一个处理函数
btn1.onclick = show1;
function show1() {
console.log('show1');
}
btn2.addEventListener("click",function () {
console.log("show");
});
btn2.addEventListener("click",function () {
console.log("show");
});
btn2.addEventListener("click",function () {
console.log("show");
});
btn2.addEventListener("click",function () {
console.log("show");
});
</script>
事件类型
各类效果演示
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div {
width: 200px;
height: 200px;
background-color: aqua;
}
</style>
</head>
<body>
<div></div>
<!-- 只有表单 元素 有获得焦点 失去焦点事件 -->
<input type="text" />
<script>
// mousemove 鼠标移动事件
// 获取div元素
let div = document.querySelector('div');
let input = document.querySelector('input');
// 绑定不同的事件
div.addEventListener("click",function () {
console.log("click 鼠标点击事件");
})
// 鼠标经过元素
div.addEventListener("mouseenter",function () {
console.log("mouseenter 鼠标经过");
})
// 鼠标离开元素
div.addEventListener("mouseleave",function () {
console.log("mouseleave 鼠标离开");
})
// 鼠标经过
// div.addEventListener("mouseover",function () {
// console.log("mouseover 鼠标经过");
// })
// 鼠标离开
// div.addEventListener("mouseout",function () {
// console.log("mouseout 离开");
// })
// 获得焦点
input.addEventListener("focus",function () {
console.log("输入框 获得焦点 ");
document.body.style.backgroundColor='#000'
})
// // 失去焦点
input.addEventListener("blur",function () {
console.log("输入框 失去焦点");
document.body.style.backgroundColor='#fff'
})
// 键盘按下事件 div不行 表单可以
// 给body标签添加比较多
document.body.addEventListener("keydown",function () {
console.log("keydown 按下");
})
// 键盘抬起
document.body.addEventListener("keyup",function () {
console.log("keyup 抬起");
})
// 输入事件 输入框
input.addEventListener("input",function () {
console.log("只要你在我的输入框输入了内容,我就触发");
})
</script>
取消绑定点击事件
<button>点击输出时间</button>
<script>
const btn = document.querySelector('button')
function func(){
console.log('一巴掌拍死你');
}
function func1(){
console.log('一巴掌拍死你,那多拍几下');
}
// 绑定事件 addEventListener可以绑定多个同名事件
btn.addEventListener('click', func)
btn.addEventListener('click', func1)
// 取消绑定 延时绑定
setTimeout(function(){
// 取消这个事件的绑定
// removeEventListener 但无法取消匿名的函数 因为没有名称 不知道取消谁
btn.removeEventListener('click',func)
}, 5000)
</script>
断点调试补充
高阶函数
掌握高阶函数用法,实现函数更多使用形式
高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的高级应用。
【值】就是 JavaScript 中的数据,如数值、字符串、布尔、对象等。
函数表达式 回调函数
1、函数表达式
函数表达式和普通函数并无本质上的区别:
普通函数的声明与调用无顺序限制,推荐做法先声明再调用
函数表达式必须要先声明再调用
<button>按钮</button>
<script>
/*
高阶函数的应用 在react阶段大量的应用
高阶函数
把一个函数 看成是个普通数据,应用在 参数 或者返回值 技术
*/
// function f1(callback) {
// callback();
// }
// function f2() {
// console.log("我就是高阶函数");
// }
// f1(f2);// f2 当成是一个普通的参数来使用(形参来使用)
// setInterval(f2,1000);// 把f2 当成是一个普通参数 传递给别人使用
// const btn=document.querySelector("button");
// btn.addEventListener("click",f2);// f2 也是高阶函数
// function getIndex() {
// let index=0;
// return function () {
// index++;
// console.log(index);
// }
// }
// const ff=getIndex();
// ff();
</script>
2、 回调函数
如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
常见的使用场景:
环境变量
环境对象
环境对象指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
作用:弄清楚this的指向,可以让我们代码更简洁
函数的调用方式不同,this 指代的对象也不同
【谁调用, this 就是谁】 是判断 this 指向的粗略规则
直接调用函数,其实相当于是 window.函数,所以 this 指代 window
<script>
let obj = {
userName:'悟空',
sayHi:function(){
console.log(this.userName);
}
}
// obj.sayHi(); // this = ?? this意思是自己 也就是obj this.userName = '悟空'
//在前端的js中,我们的全局变量,可以理解为是window的一个属性 window 是默认就存的一个全局变量 console.log(window);
// window比较特殊,我们想要使用window的一些功能的时候 是可以省略 window
</script>
排他思想
当前元素为A状态,其他元素为B状态 使用:
- 干掉所有人 使用for循环
- 复活他自己 通过this或者下标找到自己或者对应的元素
<style>
ul{
list-style: none;
display: flex;
margin: 100px auto;
}
li{
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
border: 1px solid #000;
}
</style>
</head>
<body>
<ul>
<li class="active">大家好我是1</li>
<li>战争片</li>
<li>动作片</li>
<li>玄幻片</li>
<li>爱情片</li>
<li>神话片</li>
<li>恐怖片</li>
<li>家庭伦理剧</li>
</ul>
<script>
let lis = document.querySelectorAll('li')
console.log(lis);
for (let index = 0; index < lis.length; index++) {
// 设置所有li标签的绑定事件
lis[index].addEventListener("click", function(){
// 设置所有的li标签为白色
for (let j = 0; j < lis.length; j++) {
lis[j].style.backgroundColor = '#fff'
}
// 设置点击自己变成红色
this.style.backgroundColor = 'red'
})
}
</script>
节点操作
1.1 DOM节点
DOM节点
DOM树里每一个内容都称之为节点
节点类型
元素节点 : 所有的标签 比如 body、 div html 是根节点
属性节点 : 所有的属性 比如 href
文本节点 :
所有的文本
其他
1.2 查找节点
节点关系: 父节点 子节点 兄弟节点
父节点查找:
parentNode 属性
返回最近一级的父节点 找不到返回为null
语法
子元素.parentNode
console.dir(pic1.parentNode);
关闭二维码案例
需求:多个二维码,点击谁,谁关闭
分析:
①:需要给多个按钮绑定点击事件
②:关闭的是当前的父节点
<div>
<img src="./微信图片_20220406150129.png" class="pic1">
<img src="./微信图片_20220406150310.png">
</div>
<div>
<img src="./微信图片_20220406150129.png" class="pic1">
<img src="./微信图片_20220406150310.png">
</div>
<div>
<img src="./微信图片_20220406150129.png" class="pic1">
<img src="./微信图片_20220406150310.png">
</div>
<div>
<img src="./微信图片_20220406150129.png" class="pic1">
<img src="./微信图片_20220406150310.png">
</div>
<script>
let pic1 = document.querySelectorAll('.pic1')
for (let index = 0; index < pic1.length; index++) {
pic1[index].addEventListener('click', function(){
this.parentNode.style.display = 'none'
})
}
</script>
子节点查找: childNodes
获得所有子节点、包括文本节点(空格、换行)、注释节点等
children (重点)
仅获得所有元素节点 返回的还是一个伪数组
语法
父元素.children
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul{
background-color: aqua;
padding: 20px;
margin-bottom: 10px;
}
li{
height: 30px;
background-color: yellow;
}
</style>
</head>
<body>
<ul>
<li>a1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul>
<li>b1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul>
<li>c1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
// this = 当前被点击的ul标签
// this.children 获取到所有的ul的子元素 数组
// 遍历 children 获取到中的每一个li标签
// li.style.display='none'
// 1、获取到所有的ul标签 数组
let uls = document.querySelectorAll('ul')
// 2、遍历ul数组 挨个绑定点击事件
for (let index = 0; index < uls.length; index++) {
// 3、点击事件触发
uls[index].addEventListener('click', function(){
// 对被点击的ul的children 做遍历
for (let j = 0; j < this.children.length; j++) {
// this.children[j] 表示每一个li标签
this.children[j].style.display='none'
}
})
}
</script>
兄弟关系查找:
-
下一个兄弟节点 : nextElementSibling 属性
-
上一个兄弟节点 : previousElementSibling 属性
<script>
let lis = document.querySelectorAll('li')
for (let index = 0; index < lis.length; index++) {
lis[index].addEventListener('click', function(){
// previousElementSibling 上一个兄弟 变蓝
this.previousElementSibling.style.backgroundColor = 'blue'
// nextElementSibling 下一个兄弟 被绿了
this.nextElementSibling.style.backgroundColor = 'green'
})
}
</script>
1.3 增加节点
很多情况下,我们需要在页面中增加元素
比如,点击发布按钮,可以新增一条信息
一般情况下,我们新增节点,按照如下操作:
创建一个新的节点 把创建的新的节点放入到指定的元素内部
学习路线: 创建节点 追加节点
1.创建节点
即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
创建元素节点方法:
createElement(标签名) 设置增加的节点
2.追加节点
要想在界面看到,还得插入到某个父元素中
插入到父元素的最后一个子元素:
父元素.appendChild(要插入的元素) 把增加的元素添加进去 如果本来就有 就添加在最后面
插入到父元素中某个子元素的前面
父元素.insertBefore(要插入的元素, 在那个元素前面插入)
演示
<ul></ul>
<script>
let uls = document.querySelector('ul')
// createElement(标签名) 设置增加的节点
let li = document.createElement('li')
// 父元素.appendChild(要插入的元素) 把增加的元素添加进去 如果本来就有 就添加在最后面
uls.appendChild(li)
li.innerText = 'halo'
li.style.backgroundColor = 'green'
</script>
案例
<ul class="left">
<li>龙虾</li>
<li>鲍鱼</li>
<li>皇帝蟹</li>
<li>鱼子酱</li>
</ul>
<ul class="right">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
// insertBefore 也能插入元素 功能也类似 appendchild
// 如果要插入的元素 是已经存在的 那么insertBefore作用 移动
// 如果要插入的元素 是新创建的 那么insertBefore作用 仅仅是插入
let c = document.querySelector('.left li:nth-child(3')
let two = document.querySelector('.right li:nth-child(2')
let right = document.querySelector('.right')
// 父元素.insertBefore(要插入的元素, 在那个元素前面插入)
right.insertBefore(c, two)
let li = document.createElement('li')
li.innerText = '新创建的'
right.insertBefore(li, two)
</script>
1.4 克隆节点
特殊情况下,我们新增节点,按照如下操作:
复制一个原有的节点 把复制的节点放入到指定的元素内部
克隆节点
cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
若为true,则代表克隆时会包含后代节点一起克隆--深拷贝
若为false,则代表克隆时不包含后代节点--浅拷贝 默认为false
<div class="box">
<button>点击</button>
<img src="../微信图片_20220405203436.jpg" alt="">
</div>
<script>
// 1 克隆节点 box
let box = document.querySelector('.box')
// 2 开始克隆
// let newBox = box.cloneNode() // 浅克隆 不会把div的后代节点一起克隆
let newBox = box.cloneNode(true) // true 深克隆 会把div的后代节点一起克隆
// 插入到body标签中
document.body.appendChild(newBox)
</script>
1.5 删除节点
若一个节点在页面中已不需要时,可以删除它
在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除
语法
注: 如不存在父子关系则删除不成功
删除节点和隐藏节点(display:none) 有区别的:
隐藏节点还是存在的,但是删除,则从html中删除节点
<body>
<button>删除</button>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script>
let button = document.querySelector('button')
let uls = document.querySelector('ul')
// 要删除的子元素
// let li = document.querySelector('li:nth-child(1)') // 写外面 删除li里面的第一个标签 固定第一个元素
button.addEventListener('click', function(){
// 写在里面 每一次点击按钮的时候 都是重新拿ul中的第一个li
let li = document.querySelector('li:nth-child(1)')
// 要删除的指定元素
uls.removeChild(li)
// 删除自己
// uls.remove()
})
</script>
综合案例渲染一
<link rel="stylesheet" href="./style.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<!-- 来引入外部的js -->
<script src="./data/data.js"></script>
// 定义变量 用来最终显示 标签
// 开头
let html = `
<div class="box w">
<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>
<div class="box-bd">
<ul class="clearfix">
`;
// 中间需要遍历
for (let index = 0; index < data.length; index++) {
// 在循环li标签的时候 可以动态传入对应图片和文字内容!
html += `
<li>
<img src="${data[index].src}" alt="" />
<h4>
${data[index].title}
</h4>
<div class="info">
<span>高级</span> • <span>${data[index].num}</span>人在学习
</div>
</li>
`;
}
// 结尾
html += `
</ul>
</div>
</div>
`;
// 把拼接好的html 显示到网页中
document.write(html);
</script>
综合案例渲染二
<link rel="stylesheet" href="./style.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="box w">
<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>
<div class="box-bd">
<ul class="list clearfix"></ul>
</div>
</div>
<!-- 来引入外部的js -->
<script src="./data/data.js"></script>
<script>
let ul = document.querySelector('.list')
for (let index = 0; index < data.length; index++) {
let li = document.createElement('li')
let img = document.createElement('img')
img.src = data[index].src
let h4 = document.createElement('h4')
h4.innerText = data[index].title
let div = document.createElement('div')
div.classList.add('info')
let span1 = document.createElement('span1')
span1.innerText = '高级'
let span2 = document.createElement('span2')
span2.innerText = data[index].num
let text1 = document.createTextNode('•')
let text2 = document.createTextNode('人在学习')
// 节点的类型 元素节点(标签) 文本节点
// 开始组装 append 可以同时插入多个标签
// appendChild 只能插入一个标签
div.append(span1, span2)
li.append(img, h4, div)
ul.appendChild(li)
}
</script>