1. 事件的分类
事件类型包括有系统事件和自定义事件。
2. 初始化事件
1. 创建事件对象,Event是事件对象。
bubbles:true 表示支持冒泡。
var/let 变量名 = new Event(事件类型,事件选项是否支持冒泡(可省略));
2. 创建一个事件目标对象的实例化对象 。
var/let 变量名 = new EventTarget();
EventTarget 事件目标对象,用来侦听事件,(Event)事件对象就是被侦听的事件内容 。
3. 自定义事件
1. 创建一个事件目标对象的实例化对象。
var target = new EventTarget();
2. 侦听事件:使用EventTarget的addEventListener()方法。
使用侦听事件语法:
实例对象名.addEventListener(事件类型,事件回调函数,是否捕获侦听/事件侦听选项{是否捕获侦听,是否只侦听一次})
删除侦听事件内容的语法:
实例对象名.removeEventListener(事件类型,事件回调函数);
target.addEventListener("xiaoxiao",xiaoxiaoHandler);//xiaoxiaoHandler是回调函数
function xiaoxiaoHandler(){
// 事件回调函数必须和事件侦听时的回调函数引用指向完全相同
// 删除事件侦听内容,removeEventListener(事件类型,事件回调函数)
target.removeEventListener("xiaoxiao",xiaoxiaoHandler);
console.log("aaa")
};
//尽量不要写的示范:事件回调函数尽量不要使用匿名函数。因为使用匿名函数后,这个事件将无法被删除。
target.addEventListener("xiaoxiao",function(){});
侦听事件
参数一:事件类型的注意事项!!!
1. 事件类型中自定义事件名称可以任意使用任何字符串。
2. 当接受到自定义事件这个事件类型时,直接调用事件的回调函数。
参数二:事件回调函数的注意事项!!!
1. 所有事件回调函数命名都需要使用Handler单词结尾。
2. 事件回调函数尽量不要使用匿名函数。因为使用匿名函数后,这个事件将无法被删除。
3. 事件的回调函数中有且仅有一个参数,这个参数就是抛发的事件对象。
4. 事件回调函数必须和事件侦听时的回调函数引用指向完全相同。
3. 抛发事件
抛发事件的语法:
实例对象名.dispatchEvent(事件对象名);
var evt = new Event("xiaoxiao");
target.dispatchEvent(evt);
注意!!!
1. 创建事件时,事件类型必须和侦听事件时的事件类型完全一致。
2.EventTarget使用dispatchEvent()抛发事件 ,把Event这个事件对象抛发给EventTarget。
3. 事件侦听的对象和要抛发给目标对象必须一致。
4. bubbles:true 表示支持冒泡。
自定义事件总结:
- 事件侦听的目标对象必须和事件要抛发的目标对象一致。
- 事件侦听的事件类型和要发抛发事件的事件类型必须一致。
- 必须先侦听,后抛发。
完整的案列:
//1.创建事件的实例对象
var target=new EventTarget();
//2.侦听事件
target.addEventListener("xietian",xietianHandler);
//3.抛发事件
var evt=new Event("xietian");
target.dispatchEvent(evt);
function xietianHandler(){
target.removeEventListener("xietian",xietianHandler);
console.log("aaa")
}
事件的作用:解耦。
4. 事件的基础
4.1 事件的三个阶段
案列讲解:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: red;
}
.div2 {
width: 120px;
height: 120px;
background-color: orange;
}
.div3 {
width: 75px;
height: 75px;
background-color: gold;
/* 设置div3不接受事件 */
/* pointer-events: none; */
}
/* 水平垂直居中 */
div {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<!-- 系统事件内容讲解事件基础 -->
<div class="div1">
<div class="div2">
<div class="div3"></div>
</div>
</div>
<script>
var div1 = document.querySelector(".div1");
var div2 = document.querySelector(".div2");
var div3 = document.querySelector(".div3");
// click 系统事件点击
div1.addEventListener("click", clickHandler1);
div2.addEventListener("click", clickHandler2);
div3.addEventListener("click", clickHandler3);
function clickHandler1(e){
console.log("div1被点击")
}
function clickHandler2(e){
console.log("div2被点击")
}
function clickHandler3(e){
console.log("div3被点击")
}
</script>
</body>
</html>
案列效果:
黄色区域是div3,为什么点击黄色区域div1和div2会被点击?
原理示意图:
总结:
事件在嵌套容器中,是经历三个阶段:
第一个捕获阶段,从外向内。
第二个目标阶段, 到达目标。
第三个冒泡阶段,从内向外。
默认收到事件的顺序是冒泡阶段,是从内向外。所以上述案列控制台输出的案列才是那样的。
注意:事件的顺序是可以改变的。
4.2 修改事件顺序的方法
1. 在侦听事件的方法上设置第三个参数为true,表示捕获阶段触发。
捕获阶段触发的目的可以设置在嵌套容器中谁先被触发 。
2. once:true只能触发一次事件,然后这个事件就会被删除。
再次点击是不会在触发了。
3. 既要捕获阶段触发又要只触发一次。
4.停止冒泡的方法
停止冒泡就是停止事件的继续传递。可以在捕获和冒泡阶段使用,捕获阶段使用:事件禁止传递给子元素,冒泡阶段使用:事件禁止传递给父元素。
停止冒泡的方法:e.stopPropagation();
5. 让某一个元素不接收事件的方法
在某一个元素的样式上设置pointer-events: none;属性。
5. 事件委托
事件委托 :子元素的事件委托给父元素侦听。(在是嵌套关系时,一般让父级使用侦听方法),使用事件委托时不需要使用停止冒泡。
5.1 为什么使用事件委托
1. 每个元素都侦听会占有内存。把事件委托给父元素,这样可以保证只侦听一个,减少内存的占有。
2. 因为每个元素侦听,都会触发对应的函数,就会执行多个函数,事件委托只会执行一个函数。
案列:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: red;
}
.div2 {
width: 120px;
height: 120px;
background-color: orange;
}
.div3 {
width: 75px;
height: 75px;
background-color: gold;
/* 设置div3不接受事件 */
/* pointer-events: none; */
}
/* 水平垂直居中 */
div {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<!-- 系统事件内容讲解事件基础 -->
<div class="div1">
<div class="div2">
<div class="div3"></div>
</div>
</div>
<script>
var div1 = document.querySelector(".div1");
var div2 = document.querySelector(".div2");
var div3 = document.querySelector(".div3");
// 事件委托 子元素的事件委托给父元素侦听
div1.addEventListener("click",clickHandler1);
function clickHandler1(e){
// console.log(e.target,e.currentTarget,e.srcElement,this);
console.log(e);
}
</script>
</body>
</html>
5.2 事件委托中回调函数自带属性
使用5.1中的案列做详解
div1.addEventListener("click",clickHandler1);
function clickHandler1(e){
// e 就是事件传递的Event对象
// DOM事件传递时会自带一些属性 target currentTarget srcElement
// e.target e.srcElement(IE兼容的) 是事件实际触发的目标对象
// e.currentTarget this 事件侦听的对象
// console.log(e.target,e.currentTarget,e.srcElement,this);
console.log(e);
}
注意!!!
1. e 就是事件传递的Event对象。
2. DOM事件传递时会自带一些属性 :target 、currentTarget、srcElement。
e.target 和 e.srcElement(IE兼容的) 是事件实际触发的目标对象。
e.currentTarget 和 this 是事件侦听对象(谁侦听this就是谁)。
5.3 系统事件自定义触发事件委托
方法一:var 事件对象名 = new Event("click",{bubbles:true});
1. 系统事件除了使用点击触发以外,还可以通过自定义抛发事件触发。
2. 默认事件的抛发不会向父容器冒泡,解决方案使用{bubbles:true}。{bubbles:true}设置当前自定义事件允许向父容器冒泡。
案列:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: red;
}
.div2 {
width: 120px;
height: 120px;
background-color: orange;
}
.div3 {
width: 75px;
height: 75px;
background-color: gold;
/* 设置div3不接受事件 */
/* pointer-events: none; */
}
/* 水平垂直居中 */
div {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<!-- 系统事件内容讲解事件基础 -->
<div class="div1">
<div class="div2">
<div class="div3"></div>
</div>
</div>
<script>
var div1 = document.querySelector(".div1");
var div2 = document.querySelector(".div2");
var div3 = document.querySelector(".div3");
// 事件委托 子元素的事件委托给父元素侦听
div1.addEventListener("click",clickHandler1);
function clickHandler1(e){
// e 就是事件传递的Event对象
// DOM事件传递时会自带一些属性 target currentTarget srcElement
// e.target e.srcElement(IE兼容的) 是事件实际触发的目标对象
// e.currentTarget this 事件侦听的对象
console.log(e.target,e.currentTarget,e.srcElement,this);
}
// 系统事件也可以通过自定义抛发事件触发
var evt=new Event("click",{bubbles:true});
div3.dispatchEvent(evt);
</script>
</body>
</html>
注意!!!
Event是基类,向上在向上继承MouseEvent类。所以可以使用方法二使用MouseEvent类抛发。
方法二:var 鼠标对象名 = new MouseEvent("click",{bubbles:true,clientX:100,clientY:100})
自定义抛发鼠标点击事件,在这里使用clientX,clientY分别设置被点击的位置。
5.4 事件委托案列
方法一:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
ul[show="true"] {
max-height: 2000px;
overflow: hidden;
transition: all 1s;
}
ul[show="false"] {
max-height: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<ul id="city">
<li>
北京
<ul show="true">
<li>朝阳</li>
<li>海淀</li>
<li>
昌平
<ul show="true">
<li>回龙观</li>
<li>霍营</li>
<li>龙泽</li>
<li>老牛湾</li>
</ul>
</li>
<li>东城</li>
<li>西城</li>
</ul>
</li>
<li>
河北
<ul show="true">
<li>邯郸</li>
<li>石家庄</li>
<li>保定</li>
<li>承德</li>
<li>衡水</li>
</ul>
</li>
<li>
山西
<ul show="true">
<li>临汾</li>
<li>大同</li>
<li>太原</li>
<li>晋城</li>
</ul>
</li>
<li>
陕西
<ul show="true">
<li>西安</li>
<li>咸阳</li>
<li>宝鸡</li>
<li>延安</li>
</ul>
</li>
<li>
山东
<ul show="true">
<li>烟台</li>
<li>威海</li>
<li>青岛</li>
<li>济南</li>
</ul>
</li>
</ul>
<script>
//方法一:
let lis;
init();
function init() {
//1.返回一个NodeList(迭代器)类型的集合
lis = document.querySelectorAll("li");
//2.遍历迭代器列表
lis.forEach(item => {
item.addEventListener("click", clickHandler);
})
}
function clickHandler(e) {
//3.停止冒泡
e.stopPropagation();
//4.获取到第一个子元素
if (!this.firstElementChild) return;//该编写技巧是真值缩小
//5.获取DOM标签上的属性值
if (this.firstElementChild.getAttribute("show") === "true") {
this.firstElementChild.setAttribute("show", "false");
} else {
this.firstElementChild.setAttribute("show", "true");
};
}
</script>
</body>
</html>
方法二:事件委托
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
ul[show="true"] {
max-height: 2000px;
overflow: hidden;
transition: all 1s;
}
ul[show="false"] {
max-height: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<ul id="city">
<li>
北京
<ul show="true">
<li>朝阳</li>
<li>海淀</li>
<li>
昌平
<ul show="true">
<li>回龙观</li>
<li>霍营</li>
<li>龙泽</li>
<li>老牛湾</li>
</ul>
</li>
<li>东城</li>
<li>西城</li>
</ul>
</li>
<li>
河北
<ul show="true">
<li>邯郸</li>
<li>石家庄</li>
<li>保定</li>
<li>承德</li>
<li>衡水</li>
</ul>
</li>
<li>
山西
<ul show="true">
<li>临汾</li>
<li>大同</li>
<li>太原</li>
<li>晋城</li>
</ul>
</li>
<li>
陕西
<ul show="true">
<li>西安</li>
<li>咸阳</li>
<li>宝鸡</li>
<li>延安</li>
</ul>
</li>
<li>
山东
<ul show="true">
<li>烟台</li>
<li>威海</li>
<li>青岛</li>
<li>济南</li>
</ul>
</li>
</ul>
<script>
//方法二:
let city;
init();
function init() {
//1.根据id获取元素
city = document.getElementById("city");
//2.设置侦听对象
city.addEventListener("click", clickHandler);
}
function clickHandler(e) {
//3.方法一:大写的标签名
if (e.target.nodeName !== "LI") return;
//方法二:判断点击标签不是LI
// if (!(e.target instanceof HTMLLIElement)) return;
//方法三:判断点击标签不是LI
// if (!(e.target.constructor !== HTMLLIElement)) return;
if (e.target.firstElementChild.getAttribute("show") === "true") {
e.target.firstElementChild.setAttribute("show", "false");
} else {
e.target.firstElementChild.setAttribute("show", "true");
};
}
</script>
</body>
</html>
6. 表单中事件阻止默认行为
6.1 表单中的默认行为网页跳转
1. 网址中的 ? 是 search;#是hash。
2. 页面跳转的方式:
SSR(Server Side Render) : 服务器渲染。跳转到另外的页打开。
CSR( Client Side Render) :客户端渲染。在当前页面打开。
SPA:单页面应用。 SPA 是一种特殊的 Web 应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的。一旦页面加载完成, SPA 不会因为用户的操作而进行页面的重新加载或跳转,而是利用 JavaScript 动态的变换 HTML(采用的是 div 切换显示和隐藏),从而实现UI与用户的交互。
6.2 阻止默认行为的方法
侦听对象.preventDefault();
案列:使用preventDefault()后,form表单就不会在提交数据时进行页面跳转。
<body>
<form action="#" method="get">
<input type="text" name="user">
<button type="submit">提交</button>
</form>
<script>
//1.获取元素
var form = document.querySelector("form");
//2.侦听事件,当点击提交按钮触发这个事件
form.addEventListener("submit", submitHandler);
function submitHandler() {
e.preventDefault();//阻止默认行为
console.log("aaa");
}
</script>
</body>
阻止事件默认行为:
- 提交表单 :默认提交表单会自动跳转页面,是submit事件时被阻止以后不会跳转。
- 重置表单 :默认会清空表单里的数据 ,是reset事件时被阻止后不会清除。
- 容器中文本 :默认可以选中文本,是 mousedown事件时被阻止后不能选中文本。
- 图片拖拽 :默认拖拽中会产生禁拖标志 ,是mousedown事件时被阻止后不会产生禁拖标志。
- 单击右键菜单时 :默认会有浏览器的菜单 ,是contextmenu事件时被阻止后不会有菜单。
6.3 阻止后续事件函数的执行
侦听对象.stopImmediatePropagation();
案列:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: red;
}
.div2 {
width: 120px;
height: 120px;
background-color: orange;
}
.div3 {
width: 75px;
height: 75px;
background-color: gold;
/* 设置div3不接受事件 */
/* pointer-events: none; */
}
/* 水平垂直居中 */
div {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<!-- 系统事件内容讲解事件基础 -->
<div class="div1">
<div class="div2">
<div class="div3"></div>
</div>
</div>
<script>
var div1 = document.querySelector(".div1");
var div2 = document.querySelector(".div2");
var div3 = document.querySelector(".div3");
div1.addEventListener("click", clickHandler1);
div1.addEventListener("click", clickHandler2);
div1.addEventListener("click", clickHandler3);
function clickHandler1(e) {
console.log("1");
}
function clickHandler2(e) {
// 阻止后续事件函数的执行 同一个事件
e.stopImmediatePropagation();
console.log("2");
}
function clickHandler3(e) {
console.log("3");
}
</script>
</body>
</html>
7. Event事件有哪些?
submit :表单提交事件。
reset :表单重置事件。
change :表单修改事件。
select :input文本框文本选中事件。
load :加载事件(图片加载、文件加载、通信加载)。
error :错误事件。
scroll :滚动条事件。
8. submit 表单提交事件
8.1 表单中name的作用
作用一:输入文本框必须设置name属性,标签中的name属性在提交时就会把对应的内容放在search部分。
<body>
<!-- 输入文本框 必须设置name属性,标签中的name属性在提交时就会把对应的内容放在search部分 -->
<form action="#" method="get">
<input type="text" name="user">
<button type="submit">提交</button>
</form>
</body>
作用二:在checkbox和radio,name的作用是群组,但必须设置value值。
8.2 在表单中怎样侦听
注意!!!
当提交表单和重置表单时,不能侦听按钮的click事件,必须使用表单侦听submit事件和reset事件。
8.3 Event对象事件中的属性
1. 这四个常量属性代表事件触发的时机
e.AT_TARGET : 值为2 ,目标阶段。
e.BUBBLING_PHASE :值为3 ,冒泡阶段。
e.CAPTURING_PHASE :值为1 ,捕获阶段。
e.NONE :值为0 ,无。
2. e.eventPhase :触发时机。
案列:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: red;
}
.div2 {
width: 120px;
height: 120px;
background-color: orange;
}
.div3 {
width: 75px;
height: 75px;
background-color: gold;
/* 设置div3不接受事件 */
/* pointer-events: none; */
}
/* 水平垂直居中 */
div {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<div class="div1">
<div class="div2"></div>
</div>
<script>
let div1 = document.querySelector(".div1");
let div2 = document.querySelector(".div2");
div1.addEventListener("click", clickHandler1);
div2.addEventListener("click", clickHandler2);
function clickHandler1(e) {
console.log(e.eventPhase, "div1");
}
function clickHandler2(e) {
console.log(e.eventPhase, "div2");
}
</script>
</body>
</html>
3. e.bubbles :当前事件是否冒泡,是只读属性,系统事件会自动冒泡,自定义事件不会自动冒泡。
4. e.cancelBubble :阻止当前事件冒泡,早期IE浏览器使用,等同于e.stopPropagation()。
5. e.isTrusted :触发当前事件时是系统触发还是自定义触发,true表示系统事件触发,false表示自定义事件触发。
<body>
<!-- 输入文本框 必须设置name属性,标签中的name属性在提交时就会把对应的内容放在search部分 -->
<form action="#" method="get">
<input type="text" name="user">
<input type="checkbox" name="hobby" value="游戏">游戏
<input type="checkbox" name="hobby" value="唱歌">唱歌
<input type="checkbox" name="hobby" value="跳舞">跳舞
<input type="checkbox" name="hobby" value="跑步">跑步
<button type="submit">提交</button>
</form>
<script>
//1.获取表单元素
var form = document.querySelector("form");
//2.添加侦听事件
form.addEventListener("submit", submitHandler);
//3.侦听回调函数
function submitHandler(e) {
//4.阻止默认行为(提交表单时,表单的跳转行为)
e.preventDefault();
console.log(e);
}
//4.创建事件对象
var evt = new Event("submit");
//5.自定义触发,向form表单抛发
form.dispatchEvent(evt);
</script>
</body>
6. e.defaultPrevented:判断是否阻止默认事件。
7. returnValue:阻止默认行为(早期IE浏览器的) ,等同于e.preventDefault();。
8. e.timeStamp :从页面打开到当前事件触发经过毫秒数。
9. e.type :事件触发的类型,侦听的事件类型。
9. reset 表单重置事件
注意!!!
使用e.preventDefault();阻止默认行为后,表单就不会被清除数据。
<body>
<form action="#" method="get">
<input type="text" name="user">
<input type="checkbox" name="hobby" value="游戏">游戏
<input type="checkbox" name="hobby" value="唱歌">唱歌
<input type="checkbox" name="hobby" value="跳舞">跳舞
<input type="checkbox" name="hobby" value="跑步">跑步
<button type="submit">提交</button>
<button type="reset">重置</button>
</form>
<script>
//1.获取表单元素
var form = document.querySelector("form");
//2.添加侦听事件
form.addEventListener("reset", resetHandler);
//3.侦听回调函数
function resetHandler(e) {
//4.使用阻止默认行为后,表单就不会被清除数据
e.preventDefault();
console.log("aaa");
}
</script>
</body>
10. change表单修改事件
注意!!!
1. change事件的触发需要改变表单数据中内容,并且失去焦点才能触发。
2. change事件是可以事件委托,可以委托给form。form侦听change事件,当表单元素中任意一个触发change都会收到冒泡。
<body>
<form action="#" method="get">
<input type="text" name="user">
<input type="checkbox" name="hobby" value="游戏">游戏
<input type="checkbox" name="hobby" value="唱歌">唱歌
<input type="checkbox" name="hobby" value="跳舞">跳舞
<input type="checkbox" name="hobby" value="跑步">跑步
<button type="submit">提交</button>
<button type="reset">重置</button>
</form>
<script>
//form侦听change,当表单元素中任意一个触发change都会收到冒泡
var form=document.querySelector("form");
input.addEventListener("change",changeHandler);
form.addEventListener("change",changeHandler);
function changeHandler(e){
console.log("change");
}
</script>
</body>
11. select文本框文本选中事件
注意!!!
1. select事件是针对input标签的。
2. input.selectionStart :得到文本框中选中文本的开始下标。
3. input.selectionEnd :得到文本框中选中文本的结束下标。
<body>
<form action="#" method="get">
<input type="text" name="user">
<input type="checkbox" name="hobby" value="游戏">游戏
<input type="checkbox" name="hobby" value="唱歌">唱歌
<input type="checkbox" name="hobby" value="跳舞">跳舞
<input type="checkbox" name="hobby" value="跑步">跑步
<button type="submit">提交</button>
<button type="reset">重置</button>
</form>
<script>
var input = document.querySelector("input");
input.addEventListener("select", selectHandler);
function selectHandler() {
// console.log("select");
// 得到文本框中选中文本的起始下标和结束下标
console.log(input.selectionStart, input.selectionEnd);
}
</script>
</body>
12. scroll滚动条事件
注意!!!
1. scrollTop:滚动条上下的位移。
2. scrollLeft:滚动条左右的位移。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: red;
overflow: scroll;
}
.div2 {
width: 1200px;
height: 1200px;
background-color: orange;
}
.div3 {
width: 75px;
height: 75px;
background-color: gold;
/* 设置div3不接受事件 */
/* pointer-events: none; */
}
</style>
</head>
<body>
<div class="div1">
<div class="div2"></div>
</div>
<script>
var div1 = document.querySelector(".div1");
div1.addEventListener("scroll", scrollHandler);
function scrollHandler(e) {
// scrollTop 滚动条上下的位移
// scrollLeft 滚动条左右的位移
console.log(div1.scrollTop, div1.scrollLeft)
}
</script>
</body>
</html>
13. load加载事件
var img = document.createElement("img")
// 等同于document.createElement("img") 创建图片
// 创建图片容器的宽高
var img=new Image(width,height);
1. ArrayBuffer :二进制流数组类型。
2. 图片的类型:位图、矢量图、像素图。
3. 图片中的二进制流数组 [255,255,255,255,255,255,255,255],这里有两组颜色。
RGBA :255 255 255 255,四个为一组。
4. 图片加载时会得到一个meta数据。图片加载的流程:创建文档-->创建CSS树-->创建DOM树-->创建DOM渲染树-->加载完成-->执行页面script中module内容。
<body>
<div class="div1">
<div class="div2"></div>
</div>
<img src="./img/img_23.jpg">
<script>
var img = document.createElement("img");
console.log(img.width, img.height);
</script>
</body>
注意!!!
1. link标签加载css,同步加载。
2. script标签加载js ,默认同步加载,可以异步。
3. img标签加载图片,异步加载。
4. video标签加载视频 ,异步加载。
图片加载是一个异步 ,谷歌浏览器先加载meta同步后在继续异步加载图片,所以可以看到图片的宽高。
什么是同步?什么是异步?
举例说明:
张三 吃饭用了10分钟
李四 洗碗用了5分钟
王五 洗衣服用了30分钟
同步:
张三-->李四--->王五
总共用了45分钟
异步:
张三-->10
李四-->5
王五-->30
总共用了30分钟
script标签什么时候是同步?什么时候是异步?
<!-- 默认script同步加载完成后执行js,才会继续向后 -->
<script></script>
<!-- async异步加载什么时候加载完成js,什么时候执行js,一般都会在DOM树创建完成后执行 -->
<script async></script>
<!-- defer异步加载在DOM树渲染完成后执行js -->
<script defer></script>
for循环是同步。
<script>
//循环是同步,同时创建了10次异步setTimeout,1秒后才会执行10次timeout中函数
for (var i = 0; i < 10; i++) {
var s = i;
setTimeout(() => {
console.log(i);//最后打印 i已经变成10了,执行10次就会打印10个10
// console.log(s);
}, 1000);
console.log(i);//先打印0-9
}
console.log(i);//再打印10
</script>
图片加载案例:
for (var i = 23; i < 26; i++) {
var img = new Image();
img.src = `./img/img_${i}.jpg`
// onload加载完成后,加载完成是有时间,异步
img.onload = function () {
console.log(img.src);
// console.log(this.src);
}
}
通过了解同步和异步,所以使用this代替img。
for (var i = 23; i < 26; i++) {
var img = new Image();
img.src = `./img/img_${i}.jpg`
// onload加载完成后,加载完成是有时间,异步
img.onload = function () {
console.log(this.src);
}
}
load加载事件的案例:
<body>
<img src="./img/img_23.jpg">
<script>
// for循环加载比这种一个加载完加载下一个的速度要快
let i = 23;
let arr = [];
loadImage(i);
function loadImage(i) {
var img = new Image();
img.src = `./img/img_${i}.jpg`;
img.addEventListener("load", loadHandler, { once: true });
img.addEventListener("error", errorHandler);
}
function loadHandler(e) {
arr.push(this);
i++;
if (i < 28) return loadImage(i);
arr.forEach(item => {
console.log(item.src);
})
}
function errorHandler(e) {
console.log(e)
}
</script>
</body>