一、事件链
1、事件的三个阶段:(1)先捕获,后目标,再冒泡,只能一个阶段触发程序执行,比如捕获阶段触发到了冒泡阶段就不再触发
(2)事件经过所有元素都没有被处理,这个事件就消失
(3)事件传递的过程只跟文档树的结构有关,跟界面显示的层叠效果没有任何关系
2、事件冒泡:结构上嵌套关系的元素会存在事件冒泡功能,即同一个事件,自子元素冒泡向父元素(自底向上)
事件捕获:结构上嵌套关系的元素会存在事件捕获功能,即同一事件自父元素捕获至子元素(自顶向下)
默认冒泡阶段执行的事件:onclick、attach和addEventListener传false的时候
当addEventListener绑定事件,如果第三个参数设置为true,则在捕获阶段触发事件
3、组织冒泡和系统默认事件:
阻止冒泡
box1.addEventListener("click",(el)=>{
console.log("111111",el)
})
box3.addEventListener("click",(el)=>{
console.log("222222",el)
//阻止向父级元素冒泡
el.stopPropagation()
//阻止程序传递执行冒泡
el.stopImmediatePropagation()
//ie8以下
el.cancelBubble=false
})
box3.addEventListener("click",(el)=>{
console.log("333333",el)
})
阻止冒泡、设计让监听器在捕获阶段运行等都是指的同一个事件
阻止默认事件
box.addEventListener("click",(el)=>{
console.log(66666)
el.preventDefault() //可以阻止默认事件
el.stopPropagation() //阻止不了默认的跳转页面的系统事件
el.stopImmediatePropagation() //阻止不了默认的跳转页面的系统事件
})
box.onclick=()=>{
console.log("hello")
}
二、事件代理
事件代理:利用冒泡事件,只指定一个事件处理程序就可以管理某一类型的所有事件
无论事件触发时,是不是目标对象的监听器,在监听器内部的事件对象event中都可以访问这个事件的目标对象,利用这个特点去绑定事件给父级元素,来代理子级元素的业务,这种设计就是事件代理
事件代理减少占用内存,提高性能,解决动态的事件绑定
<style>
.box2{
width: 70px;
background-color: chartreuse;
margin-top: 5px;
}
button{
margin-top: 6px;
}
</style>
<div class="box1">
<div class="box2">信息1</div>
<div class="box2">信息2</div>
<div class="box2">信息3</div>
<div class="box2">信息4</div>
</div>
<button onclick="qut()">请求新的信息</button>
<script>
function qut() {
var box1 = document.querySelector(".box1")
var box2 = document.createElement("div")
box2.innerHTML = "新的信息"
box2.className = "box2"
box1.appendChild(box2)
}
var box1 = document.querySelector(".box1")
box1.addEventListener("click", function (el) {
console.log(el.target.innerHTML)
})
</script>
三、页面渲染
程序执行时,常常会操作页面,引起重绘、回流
频繁的重绘、回流会造成页面性能不好==>页面卡顿、迟缓、手机发烫
因此操作页面时:尽量避免高频重绘,使用框架(MVVM)
尽量避免高频重绘案例:
let tb=document.querySelector(".box")
for(let i=0;i<100;i++){
let tr=document.createElement("tr")
tb.appendChild(tr)
for(let j=0;j<100;j++){
let dt=new Date().getTime()
let td=document.createElement("td")
td.innerHTML=dt
tr.appendChild(td)
}
}
//回档了一万零一百次
//创建一个“冰”元素优化,减少回档次数
let tb=document.querySelector("#box")
let fra1=document.createDocumentFragment() //它在内存中还不在文档中
for(let i=0;i<100;i++){
let tr=document.createElement("tr")
fra1.appendChild(tr)
for(let j=0;j<100;j++){
let dt=new Date().getTime()
let td=document.createElement("td")
td.innerHTML=dt
tr.appendChild(td)
}
}
tb.appendChild(fra1) //它自己不会添加到文档树中用于渲染,但是它的子代元素都会添加进去
//回档了1次
四、style的操作
获取script脚本节点后面加载的元素节点,是获取不了的,因为文档的加载是按照文档树的顺序加载的
<style>
.box {
width: 400px;
height: 300px;
background-color: brown;
cursor: pointer;
}
</style>
<div class='box' style="color: red;font-size: 18px;">666</div>
<script>
var color1=document.querySelector('.box').style.color
var width1=document.querySelector('.box').style.width //无法获取
var box2=document.querySelector(".box2")
console.log(box2)
</script>
解决方案:
(1)当页面加载完成的事件触发,再去执行获取节点的方式
function fn(){
var box2=document.querySelector(".box2")
console.log(box2)
}
window.onload=fn
(2)script-- defer async 修饰src如何加载外部js资源的异步属性
//代码写到js文件中:
var box2 = document.querySelector(".box2")
console.log(box2)
五、防抖与节流
节流::n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
//节流 (比如让高频触发的业务频率降下来)
document.onmousemove = jieliu(function () {
console.log(666)
}, 20)
function jieliu(cb, daley) {
var timer = null;
return function () {
// console.log(66666,timer)
if (!timer) {
timer = setTimeout(() => {
cb();
timer = null
}, daley)
}
}
}
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
//防抖
document.onclick = fangdou(function (e) {
console.log(6666)
}, 1000)
function fangdou(cb, delay) {
var timer = null;
return function () {
//return这个函数频率很高 想办法让cb()执行慢下来:防抖
clearTimeout(timer)
timer = setTimeout(function () {
cb()
}, delay)
}
}
//防抖与节流代码优化
function jieliu(cb, daley) {
var timer = null;
return function () {
// console.log(66666,timer)
// this是事件函数的this
let arg = arguments
if (!timer) {
timer = setTimeout(() => {
cb.apply(this, arg);
timer = null
}, daley)
}
}
}
let timefn = jieliu(function (e) {
// console.log(e.offsetX,e.pageX)
box.style.left = e.pageX - box.offsetWidth / 2 + "px"
box.style.top = e.pageY - box.offsetHeight / 2 + "px"
console.log(11111)
}, 17)
document.addEventListener("mousemove", timefn)
六、懒加载与预加载
懒加载:延迟加载,达到加载条件时再加载
预加载:提前加载,当用户需要查看时是直接从浏览器缓存里取资源,用户操作体验速度快