Web APIs _day03

晚风的街 2024-08-12 10:03:01 阅读 60

事件

事件流与两个阶段说明

事件流指的是事件完整执行过程中的流动路径(事件捕获=>事件目标阶段=>事件冒泡)

简单来说:捕获阶段是从父到子    冒泡阶段是从子到父

实际工作都是使用事件冒泡为主

事件捕获 

概念:从DOM的根元素开始去执行对应的事件 (从外到里)

语法:DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)

注意:

(1)addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)

(2)若传入false代表冒泡阶段触发,默认就是false。

(3)若是用 L0 事件监听,则只有冒泡阶段,没有捕获。

(4)捕获机制必须使用事件监听的形式注册

事件冒泡

概念: 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。

当一个元素触发事件后,会依次向上调用所有父级元素的同名事件。(事件的类型一样)事件冒泡是默认存在的L2事件监听第三个参数是 false,或者默认都是冒泡。

阻止冒泡

原因:因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素。

前提:阻止事件冒泡需要拿到事件对象

语法:事件对象.stopPropagation()

注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。

原因:阻止(元素)默认行为的发生,比如阻止链接的跳转,表单域跳转。

语法:e.preventDefault()

<code><form action="http://www.baidu.com">code>

<input type="submit" value="提交">code>

</form>

<script>

const form = document.querySelector('form')

form.addEventListener('click', function (e) {

//阻止表单默认提交行为

e.preventDefault()

})

</script>

 解绑事件

on事件

//直接使用null覆盖偶就可以实现事件的解绑

//绑定事件

btn.onclick=function(){

alert('你好')

}

//解绑事件

btn.onclick = null

addEventListener方式

语法:removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段]) ([ ]里面的可以省略不写)

注意:匿名函数无法被解绑,必须改写成有具体名的函数。

function fn(){

alert('你好')

}

//绑定事件

btn.addEventListener('click',fn)

//解绑事件

btn.removeEventListener('click',fn)

 鼠标经过事件的区别

mouseover 和 mouseout 会有冒泡效果mouseenter 和 mouseleave 没有冒泡效果 (推荐)

两种注册事件的区别

传统on注册(L0)

(1)同一个对象,后面注册的事件会覆盖前面注册(同一个事件)。

(2)直接使用null覆盖偶就可以实现事件的解绑

(3)都是冒泡阶段执行的

事件监听注册(L2)

(1)语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)

(2)后面注册的事件不会覆盖前面注册的事件(同一个事件)

(3)可以通过第三个参数去确定是在冒泡或者捕获阶段执行

(4)必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)

(5)匿名函数无法被解绑

事件委托

优点:减少注册次数,可以提高程序性能。

原理:事件委托其实是利用事件冒泡的特点。(给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事 件)

语法:父级元素.addEventListener('click', function(){}) 执行父级点击事件

           事件对象.target. tagName 可以获得真正触发事件的元素

tab栏切换改造 

<div class="tab">code>

<div class="tab-nav">code>

<h3>每日特价</h3>

<ul>

<li><a class="active" href="javascript:;" data-id='0'>精选</a></li>code>

<li><a href="javascript:;" data-id='1'>美食</a></li>code>

<li><a href="javascript:;" data-id='2'>百货</a></li>code>

<li><a href="javascript:;" data-id='3'>个护</a></li>code>

<li><a href="javascript:;" data-id='4'>预告</a></li>code>

</ul>

</div>

<div class="tab-content">code>

<div class="item active"><img src="./images/tab00.png" alt="" /></div>code>

<div class="item"><img src="./images/tab01.png" alt="" /></div>code>

<div class="item"><img src="./images/tab02.png" alt="" /></div>code>

<div class="item"><img src="./images/tab03.png" alt="" /></div>code>

<div class="item"><img src="./images/tab04.png" alt="" /></div>code>

</div>

</div>

<script>

//采取事件委托

//获取父级元素

const ul = document.querySelector('.tab-nav ul')

const items = document.querySelectorAll('.tab-content .item')

//添加点击事件 事件对象e

ul.addEventListener('click', function (e) {

//只有点击a标签才能进行添加和删除类的操作

if (e.target.tagName === "A") {

// 排他思想

// 干掉别人 移除类active

document.querySelector('.tab-nav .active').classList.remove('active')

//当前元素添加active 当前元素是e.target

//this指向的是ul,不能用this

e.target.classList.add('active')

// 下面5个大盒子 e.target.dataset.id获取的是字符串 '0'+1为'01'下面会报错

const i = +(e.target.dataset.id)

document.querySelector('.tab-content .active').classList.remove('active')

//方法1

//没有i,则需要自定义属性

// document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')

//方法2

//获取item得到的是一个数组

items[i].classList.add('active')

}

})

//以下是利用for循环完成的

// for (let i = 0; i < as.length; i++) {

// // console.log(as[i])

// // 要给 5个链接绑定鼠标经过事件

// as[i].addEventListener('mouseenter', function () {

// // console.log('鼠标经过')

// // 排他思想

// // 干掉别人 移除类active

// document.querySelector('.tab-nav .active').classList.remove('active')

// // 我添加类 active this 当前的那个 a

// this.classList.add('active')

// // 下面5个大盒子 一一对应 .item

// // 干掉别人

// document.querySelector('.tab-content .active').classList.remove('active')

// // 对应序号的那个 item 显示 添加 active 类

// document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')

// })

// }

</script>

其他事件

页面加载事件

事件名:load

加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件

监听页面所有资源加载完毕:给 window 添加 load 事件

语法:windows.addEventListener('load',function(){})

注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件。

事件名:DOMContentLoaded

当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载

语法:document.addEventListener('DOMContentLoaded',function(){})

监听页面DOM加载完毕:给 document 添加 DOMContentLoaded 事件

元素滚动事件

事件名:scroll                 

监听整个页面滚动:给 window 或 document 添加 scroll 事件

语法:windows.addEventListener('scroll',function(){})

监听某个元素的内部滚动直接给某个元素加即可

元素.scrollTo(x, y)

scrollTo() 方法可把内容滚动到指定的坐标

scrollLeft和scrollTop (属性)

(1)获取被卷去的大小

(2)获取元素内容往左、往上滚出去看不到的距离。

(3)这两个值是可读写的(可读可赋值)

<code>//页面滚动事件

windows.addEventListener('scroll',function(){

//document.documentElement HTML 文档返回对象为HTML元素

const n = document.documentElement.scrollTop

console.log(n)

})

页面滚动显示隐藏侧边栏 

<script>

//获取元素

const elevator = document.querySelector('.xtx-elevator ')

const entry = document.querySelector('.xtx_entry ')

//当前页面大于300px,就显示电梯

//给页面添加滚动事件

window.addEventListener('scroll', function () {

const n = document.documentElement.scrollTop

// if (n >= 300) {

// elevator.style.opacity = 1

// }

// else {

// elevator.style.opacity = 0

// }

elevator.style.opacity = n >= entry.offsetTop ? 1 : 0

// console.log(entry.offsetTop);

})

//点击返回顶部

const backTop = document.querySelector('#backTop')

backTop.addEventListener('click', function () {

document.documentElement.scrollTop = 0

//window.scrollTo(0,0) 了解

})

</script>

页面尺寸事件

在窗口尺寸改变的时候触发事件:

windows.addEventListener(' resize ',function(){})

获取宽高

(1)获取元素的可见部分宽高(不包含边框,margin,滚动条等)

(2)clientWidth和clientHeight

元素尺寸与位置

获取宽高:

(1)offsetWidth和offsetHeight

(2)获取元素的自身宽高、包含元素自身设置的宽高、padding、border。

(3)获取出来的是数值,方便计算。

(4)注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0。

获取位置:

(1)offsetLeft和offsetTop 注意是只读属性

(2)获取元素距离自己定位父级元素的左、上距离(受父级定位的影响)

offsetTop和offsetLeft 得到位置以谁为准? 

(1)带有定位的父级

(2)如果都没有则以文档左上角为准

仿新浪固定导航栏案例

<code><div class="content"></div>code>

<div class="backtop">code>

<img src="./images/close2.png" alt="">code>

<a href="javascript:;"></a>code>

</div>

<script>

// 0 获取元素

let backtop = document.querySelector('.backtop')

// 页面滚动事件

window.addEventListener('scroll', function () {

// 2. 页面检测滚动的距离

// console.log(document.documentElement.scrollTop)

let num = document.documentElement.scrollTop

// 3. 进行判断显示和隐藏

if (num >= 500) {

//显示那个元素

backtop.style.display = 'block'

} else {

// 否则隐藏元素

backtop.style.display = 'none'

}

})

// 点击链接返回顶部 backtop.children[1]

backtop.children[1].addEventListener('click', function () {

// 返回顶部

// scrollTop 可读写

document.documentElement.scrollTop = 0

})

</script>

总结

综合案例

复选框

<code><script>

//获取大复选框

const allCheck = document.querySelector('#checkAll')

//获取小复选框

const cks = document.querySelectorAll('.ck')

//添加大复选框点击事件

allCheck.addEventListener('click', function () {

for (let i = 0; i < cks.length; i++) {

cks[i].checked = this.checked

}

})

//添加小复选框点击事件

for (let i = 0; i < cks.length; i++) {

cks[i].addEventListener('click', function () {

allCheck.checked = document.querySelectorAll('.ck:checked').length === cks.length

})

}

</script>

电梯导航

<code><div class="aside">code>

<div class="item active">男装/女装</div>code>

<div class="item">儿童服装/游乐园</div>code>

<div class="item">电子产品</div>code>

<div class="item">电影/美食</div>code>

</div>

<div class="content">code>

<div class="neirong content1">男装/女装</div>code>

<div class="neirong content2">儿童服装/游乐园</div>code>

<div class="neirong content3">电子产品</div>code>

<div class="neirong content4">电影/美食</div>code>

</div>

<script>

//获取元素

const items = document.querySelectorAll('.aside .item')

const neirongs = document.querySelectorAll('.content .neirong')

// 左侧aside 模块 点击谁,谁高亮

for (let i = 0; i < items.length; i++) {

items[i].addEventListener('click', function () {

// 找到上一个active 移除类

document.querySelector('.aside .active').classList.remove('active')

// 点击谁谁添加类

this.classList.add('active')

// 右侧内容跟随走动 让页面滚动到对应的offsetTop值位置

// console.log(neirongs[i].offsetTop) 找到数据值 不用给单位

document.documentElement.scrollTop = neirongs[i].offsetTop

})

}

</script>

<code><script>

//第一大模块

(function () {

//获取元素

const elevator = document.querySelector('.xtx-elevator ')

const entry = document.querySelector('.xtx_entry ')

//当前页面大于300px,就显示电梯

//给页面添加滚动事件

window.addEventListener('scroll', function () {

const n = document.documentElement.scrollTop

// if (n >= 300) {

// elevator.style.opacity = 1

// }

// else {

// elevator.style.opacity = 0

// }

elevator.style.opacity = n >= entry.offsetTop ? 1 : 0

// console.log(entry.offsetTop);

})

//点击返回顶部

const backTop = document.querySelector('#backTop')

backTop.addEventListener('click', function () {

document.documentElement.scrollTop = 0

//window.scrollTo(0,0) 了解

})

})();

(function () {

//点击页面可以滑动

const list = document.querySelector('.xtx-elevator-list')

list.addEventListener('click', function (e) {

if (e.target.tagName === 'A' && e.target.dataset.name) {

//先获取这个类名

const old = document.querySelector('.xtx-elevator-list .active')

if (old) old.classList.remove('active')

//当前元素添加active

e.target.classList.add('active')

//获得自定义属性

//根据小盒子的属性值选择合适的大盒子

const top = document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTop

//获取对应的大盒子内容,让页面滚动到对应的位置

document.documentElement.scrollTop = top

}

})

//页面滚动,可以根据大盒子选小盒子,添加active

window.addEventListener('scroll', function () {

//先获取这个类名

const old = document.querySelector('.xtx-elevator-list .active')

if (old) old.classList.remove('active')

//判断当前滑动的位置选择小盒子

const news = document.querySelector('.xtx_goods_new')

const popular = document.querySelector('.xtx_goods_popular')

const brand = document.querySelector('.xtx_goods_brand')

const topic = document.querySelector('.xtx_goods_topic')

const n = document.documentElement.scrollTop

if (n >= news.offsetTop && n < popular.offsetTop) {

//选择第一个小盒子

document.querySelector('[data-name=new]').classList.add('active')

}

else if (n >= popular.offsetTop && n < brand.offsetTop) {

document.querySelector('[data-name=popular]').classList.add('active')

}

else if (n >= brand.offsetTop && n < topic.offsetTop) {

document.querySelector('[data-name=brand]').classList.add('active')

}

else if (n >= topic.offsetTop) {

document.querySelector('[data-name=topic]').classList.add('active')

}

})

})();

</script>

 

购物车加减操作

<code><div>

<input type="text" id="total" value="0" readonly>code>

<input type="button" value="+" id="add">code>

<input type="button" value="-" id="reduce" disabled>code>

<script>

//获取元素

const total = document.querySelector('#total')

const add = document.querySelector('#add')

const reduce = document.querySelector('#reduce')

//加号操作

add.addEventListener('click', function () {

// console.log(typeof total.value) string

// i++ 隐式转换

total.value++

reduce.disabled = false

})

//减号操作

reduce.addEventListener('click', function () {

// console.log(typeof total.value) string

// i-- 隐式转换

total.value--

add.disabled = false

})

// 2 === '2'

</script>

</div>



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。