DOM操作

一、事件链

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)

六、懒加载与预加载

懒加载:延迟加载,达到加载条件时再加载

预加载:提前加载,当用户需要查看时是直接从浏览器缓存里取资源,用户操作体验速度快

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值