事件流
事件完整执行过程中的流动路径
捕获阶段->目标阶段->冒泡阶段
window->document->html->body->div->body->html->document->window
.事件捕获:
当一个元素的事件被触发时,会从DOM的根元素开始依次调用 同名事件 ( 从外到里 )
.语法:DOM.addEventListener( 事件类型,时间处理函数,是否使用捕获机制)
addEventListener第三个参数传入 true 代表是捕获阶段触发; 从DOM的 根元素 开始去执行对应的事件 ( 从外到里、父到子 )
若传入false代表冒泡阶段触发,默认就是 false
事件冒泡:
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中 依次被触发 。这一过程被称为事件冒泡
<div class="box">
<div class="son">son</div>
<script>
const box = document.querySelector('.box')
const son = document.querySelector('.son')
/* window.addEventListener(
'click',
function () {
console.log('window')
},
true
) // true表示捕获阶段 */
document.addEventListener(
'click',
function () {
console.log('document')
},
true
)
document.documentElement.addEventListener(
'click',
function () {
console.log('html')
},
true
)
document.body.addEventListener(
'click',
function () {
console.log('body')
},
true
)
box.addEventListener(
'click',
function () {
console.log('box')
},
true
)
son.addEventListener('click', function () {
console.log('son')
})
son.addEventListener(
'click',
function () {
console.log('son')
},
true
)
window.addEventListener(
'click',
function () {
console.log('window')
},
false
) // false表示冒泡阶段
document.addEventListener('click', function () {
console.log('document')
})
document.documentElement.addEventListener('click', function () {
console.log('html')
})
document.body.addEventListener('click', function () {
console.log('body')
})
box.addEventListener('click', function () {
console.log('box')
})
事件委托(事件委派、事件代理)
原理:事件委托其实是利用 事件冒泡 的特点给 父元素注册事件 ,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
优点:1 提高代码执行效率 2 对动态生成的子元素也生效
缺点直接操作儿子缺点 无法获取后面动态生成的元素
利用事件委托方式如何得到当前点击的元素呢?
实现: 事件对象. target. tagName 可以获得真正触发事件的元素
ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>
<script>
const ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
console.log('ul')
console.log(e.target) // 真正触发的元素
e.target.style.backgroundColor = 'red'
})
</script>
解绑dom0级事件
语法 事件源.on事件类型 = null
解绑dom2级事件
语法 事件源.removeEventListener('事件类型', 要解绑的事件处理函数)
注意 如果用dom2级解绑, 绑定的时候的事件处理函数必须要在外面单独定义,用函数名的形式进行绑定
<button>dom0级事件</button>
<button>dom2级事件</button>
<script>
const btn = document.querySelectorAll('button')
btn[0].onclick = function () {
alert('dom0')
btn.onclick = null
}
function f() {
alert('dom2')
// 解除事件绑定
btn[1].removeEventListener('click', f)
}
btn[1].addEventListener('click', f)
</script>
阻止 元素发生 默认的行为 ; 例如: 当点击提交按钮时阻止对表单的提交 ;阻止链接的跳转
超链接点击 默认会跳转等等
语法: 事件对象 . preventDefault ()
<form action="https://www.baidu.com">
<input type="text" name="username" />
<button>按钮</button>
</form>
<a href="https://www.baidu.com">百度</a>
<script>
const alink = document.querySelector('a')
const form = document.querySelector('form')
const ipt = document.querySelector('input[name=username]')
alink.addEventListener('click', function (e) {
e.preventDefault() // 阻止跳转
alert('ok')
})
form.addEventListener('submit', function (e) {
if (ipt.value.trim() === '') {
e.preventDefault() // 阻止默认跳转
}
})
窗口加载 onload
加载 外部资源 (如图片、外联CSS和JavaScript等) 加载完毕时触发的事件
window.addEventListener('load', function () {
const btn = document.querySelector('button')
console.log(btn)
btn.addEventListener('click', function () {
alert('中国人民万岁')
})
DOMContentLoaded 当dom元素加载完毕就执行 不必等其他资源加载完
document.addEventListener('DOMContentLoaded', function () {
const btn = document.querySelector('button')
console.log(btn)
btn.addEventListener('click', function () {
alert('中国人民万岁')
})
})
获取屏幕尺寸
会在窗口尺寸改变的时候触发事件:
2.语法:window.addEventListener('resize', function ()
window.addEventListener('resize', function () {
console.log('窗口大小改变了')
console.log(document.documentElement.clientWidth)
})
元素偏移:offset -- 内容+padding+border
offsetWidth -- 元素布局宽度
offsetHeight -- 元素布局高度
offsetTop -- 元素顶部到有定位父元素顶部的距离,如果父元素没有定位就以body为参照
offsetParent -- 返回有定位的父元素,没有就返回body
元素可视:client -- 内容+padding
clientWidth -- 内容+padding的宽度
clientHeight -- 内容+padding的高度
clientTop -- 元素上边框的宽
元素滚动:scroll -- 实际内容+padding
scrollWidth -- 实际内容的宽度
scrollHeight -- 实际内容的高度
scrollTop -- 滚动条被卷起的长度
<style>
.wrapper {
width: 300px;
height: 300px;
background-color: red;
padding: 20px;
border: 6px dashed black;
}
.wrapper .box {
width: 100px;
height: 100px;
background-color: blue;
margin: 0 auto;
border: 2px solid green;
padding: 10px;
overflow: hidden;
white-space: nowrap;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box">
内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容
</div>
</div>
<script>
// 元素尺寸或位置 client offset scroll
const wrapper_box = document.querySelector('.wrapper')
const box = document.querySelector('.box')
console.log(wrapper_box.clientWidth) // 340
console.log(wrapper_box.clientHeight)//340
console.log(box.clientWidth) //120
console.log(box.clientHeight)//120
console.log('=====================')
console.log(wrapper_box.offsetWidth) // 351
console.log(wrapper_box.offsetHeight)//351
console.log(box.offsetWidth) // 123
console.log(box.offsetHeight)//123
console.log('=====================')
console.log(box.scrollWidth) //596 实际内容区域(包括隐藏的内容)
console.log(document.documentElement.scrollTop) // 页面被卷去的尺寸
</script>