1.认识事件
认识事件(DOM 事件)
+ 就是和页面的某一个元素约定好一个事情, 当行为发生的时候, 执行指定的一段代码
事件三要素:
1. 事件源: 给谁绑定事件
2. 事件类型: 绑定什么事件
3. 事件处理函数: 当行为发生的时候, 所执行的函数
+ 例子:
box.onclick = function () { }
=> box 就是事件源
=> click 是事件类型
=> function () {} 事件处理函数
=> 和浏览器做了一个约定
-> 当有 click 行为发生在 box 这个元素身上的时候, 执行后面的函数
事件绑定的方式
+ DOM 0级 事件
=> 语法: 事件源.on事件类型 = 事件处理函数
=> 同一个事件源的同一个事件类型只能绑定一个事件处理函数
+ DOM 2级 事件(事件侦听器 / 事件监听器)
=> 标准浏览器
-> 语法: 事件源.addEventListener('事件类型', 事件处理函数)
-> 特点: 可以给同一个事件源的同一个事件类型绑定多个事件处理函数, 顺序绑定顺序执行
=> IE 低版本
-> 语法: 事件源.attachEvent('on事件类型', 事件处理函数)
-> 特点: 可以给同一个事件源的同一个事件类型绑定多个事件处理函数, 顺序绑定倒序执行
事件解绑的方式
+ DOM 0级 事件
=> 语法: 事件源.事件类型 = null
+ DOM 2级 事件
=> 标准浏览器: 事件源.removeEventListener('事件类型', 要解绑的事件处理函数)
=> IE 低版本: 事件源.detachEVent('on事件类型', 要解绑的事件处理函数)
=> 注意: DOM 2级 事件, 如果你需要解绑, 那么绑定的时候, 必须要把函数单独书写出来, 以函数名的形式进行绑定和解绑
var ele = document.querySelector('div')
var btn = document.querySelector('button')
ele.onclick = function () { console.log('我是第一个事件处理函数') }
ele.addEventListener('click', function () { console.log('DOM 2级 事件 111') })
ele.addEventListener('click', function () { console.log('DOM 2级 事件 222') })
ele.addEventListener('click', function () { console.log('DOM 2级 事件 333') })
ele.onclick = function () { console.log('我被点击了') }
function handler() { console.log(222) }
ele.addEventListener('click', function () { console.log(111) })
ele.addEventListener('click', handler)
btn.onclick = function () {
console.log('我要解绑事件了')
ele.onclick = null
ele.removeEventListener('click', handler)
console.log('解绑事件的代码执行了')
}
2.事件对象
事件对象
+ 一个记录本次事件触发的时候, 所有的相关信息, 一个对象数据类型
+ 例子: 当一个鼠标事件发生的时候
=> 针对当前本次的事件触发会有一些信息出现
-> 坐标位置 x: 100, y: 200
-> 谁触发的事件: div
-> 什么事件: click
-> ...
=> 浏览器把这些信息记录下来了
-> 放在了一个对象数据类型内
{
x: 100,
y: 200,
target: div,
type: 'click',
...
}
+ 当你需要获取一些本次事件相关的信息的时候
=> 需要先拿到事件对象
=> 从事件对象内去获取
获取事件对象的方式
=> 标准浏览器: 直接给事件处理函数书写形参, 会在事件触发的时候, 有浏览器自动传递实参
=> IE 低版本: 直接使用 window.event
=> 兼容: e = e || window.event
var ele = document.querySelector('div')
ele.onclick = function (e) {
// 这个事件处理函数的第一个形参
// 会在你触发该事件的时候, 有浏览器传递实参
// 传递进来的实参就是本次事件触发的事件对象
// 处理事件对象兼容
e = e || window.event
}
3.事件的传播
事件的传播
+ 当行为发生的时候, 按照元素结构父级的顺序, 向上传递该事件行为, 直到 window 为止
问题1: 如果 inner 身上没有绑定点击事件, 会不会继续传播了 ?
=> 会
=> 因为传递的是 事件行为
问题2: 如果 center 身上没有绑定点击事件, 会不会继续传播了 ?
=> 会
=> 因为传递的是 事件行为
问题3: 如果点击在 center 身上, 会不会传播到 inner 身上 ?
=> 不会
=> 因为是按照 结构父级 的顺序向上传播
在事件对象内, 有一个成员叫做 path
=> 表示本次事件触发的时候, 事件传播的路径
事件流机制(了解)
=> 当一个行为发生的时候, 从浏览器反映到元素身上的过程
=> 并且包含触发事件的时机问题
=> 机制是 浏览器 给的
=> 所有浏览器的共同点
-> 虽然一次事件, 一个内容接受了两次事件行为, 但是是在一次事件内接受的
-> 只会触发一次事件处理函数
=> 各个浏览器对事件流解析的不通电
-> 标准浏览器: 默认是在 冒泡阶段 触发事件函数
-> IE 低版本: 只能在 冒泡阶段 触发事件函数
事件流的三个阶段
=> 事件捕获: 从 window 向 事件目标 传播的过程
=> 事件目标: 准确触发事件的元素
=> 事件冒泡: 从 事件目标 向 window 传播的过程
在捕获阶段触发事件
=> 只能在标准浏览器内使用
=> 并且一定是 DOM 2级 事件绑定方式才可以
=> addEventListener('事件类型', 事件处理函数, 冒泡或者捕获阶段触发)
-> 冒泡或者捕获阶段触发
-> 默认值是 false, 表示 冒泡(从里面往外面穿)
-> 选填内容 true, 表示 捕获(从外面往里面穿)
var outer = document.querySelector('.outer')
var center = document.querySelector('.center')
var inner = document.querySelector('.inner')
inner.onclick = function (e) { console.log('inner') }
center.onclick = function () { console.log('center') }
outer.onclick = function () { console.log('outer') }
document.body.onclick = function () { console.log('body') }
document.documentElement.onclick = function () { console.log('html') }
document.onclick = function () { console.log('document') }
window.onclick = function () { console.log('window') }
inner.addEventListener('click', function () { console.log('inner') }, false)
center.addEventListener('click', function () { console.log('center') }, false)
outer.addEventListener('click', function () { console.log('outer') }, true)
document.body.addEventListener('click', function () { console.log('body') }, false)
document.documentElement.addEventListener('click', function () { console.log('html') }, false)
document.addEventListener('click', function () { console.log('document') }, false)
window.addEventListener('click', function () { console.log('window') }, false)
inner.addEventListener('click', function () { console.log('inner') }, true)
center.addEventListener('click', function () { console.log('center') }, true)
outer.addEventListener('click', function () { console.log('outer') }, true)
document.body.addEventListener('click', function () { console.log('body') }, true)
document.documentElement.addEventListener('click', function () { console.log('html') }, true)
document.addEventListener('click', function () { console.log('document') }, true)
window.addEventListener('click', function () { console.log('window') }, true)
inner.addEventListener('click', function () { console.log('inner') }, false)
center.addEventListener('click', function () { console.log('center') }, false)
outer.addEventListener('click', function () { console.log('outer') }, false)
document.body.addEventListener('click', function () { console.log('body') }, false)
document.documentElement.addEventListener('click', function () { console.log('html') }, false)
document.addEventListener('click', function () { console.log('document') }, false)
window.addEventListener
4.阻止事件的传播(冒泡)
阻止事件传播
+ 就是不让事件行为继续向上传递
+ 到自己为止了
语法:
=> 标准浏览器: 事件对象.stopPropagation()
=> IE 低版本: 事件对象.cancelBubble = true
var eleDiv = document.querySelector('div')
var eleP = document.querySelector('p')
eleDiv.onclick = function () {
console.log(window.getComputedStyle(this).backgroundColor)
}
eleP.onclick = function (e) {
console.log(window.getComputedStyle(this).backgroundColor)
}

5.阻止默认行为
阻止默认行为
默认行为
=> 元素本身自带的行为, 不需要你进行事件绑定
-> 鼠标右键单击事件: 弹出菜单
-> a 标签的点击事件: 跳转连接
-> 表单的提交按钮: 表单提交
阻止默认行为
=> 在同类型事件内, 阻止默认出现的行为
=> 标准浏览器: 事件对象.preventDefault()
=> IE 低版本: 事件对象.returnValue = false
=> 通用: return false
window.oncontextmenu = function (e) {
console.log('右键单击')
return false
}
document.querySelector('form').onsubmit = function (e) {
console.log('对表单填写的内容进行验证, 验证合适以后在发给服务器')
return false
}
5.1阻止默认行为例子补充
有很多的系统事件除了会触发执行函数,还会触发执行部分特有的内容
1.比如submit,当收到这个事件后会跳转到表单所对应的action地址
reset...
2.比如超链接点击时,默认有hash改变添加历史记录,使用e.preventDefault();就不会有hash改变了,也不会有历史记录
3.图片拖拽时产生禁拖标记,使用它也可以不产生禁拖标记
4.侦听mousedown事件时,如果设置e.preventDefault();就不能拖选中文本内容了
5.当点击鼠标右键时,一般会触发右键菜单,e.preventDefault();不会触发右键菜单
例:
4.submit演示-阻止默认行为
var form=document.querySelector("form");
form.addEventListener("submit",submitHandler);
function submitHandler(e){
console.log(e)
e.preventDefault();
}
4.1 操作超链接试试-阻止默认行为
var a=document.querySelector("a");
a.addEventListener("click",clickHandler);
function clickHandler(e){
e.preventDefault();
}
4.2 默认文字选中 mousedown 鼠标按下操作
var div=document.querySelector("div");
div.addEventListener("mousedown",mouseHandler);
function mouseHandler(e){
e.preventDefault();
}
4.3 contextmenu鼠标右键函数
document.addEventListener("contextmenu",contextmenuHandler);
function contextmenuHandler(e){
e.preventDefault();
}
6.阻止当前事件类型的函数列表中的后续函数的执行
e.stopImmediatePropagation();
div1.addEventListener("click",clickHandler1);
div1.addEventListener("click",clickHandler2);
div1.addEventListener("click",clickHandler3);
div1.addEventListener("mousedown",clickHandler4);
function clickHandler1(e){
console.log("a")
}
function clickHandler2(e){
console.log("b");
e.stopImmediatePropagation();
}
function clickHandler3(e){
console.log("c")
}
function clickHandler4(e){
console.log("d");
}
7.事件委托
事件委托
+ 把自己的事件委托给某一个结构父级
循环绑定事件
+ 缺点:
1. 对于后期动态操作的元素不够友好
2. 大量的 DOM 操作, 性能在浪费
事件委托
+ 优点:
1. 对于后期动态操作的元素足够友好
2. 少量的 DOM 操作
将所有事件委托给父级元素的方式叫做事件委托
把所有子元素的事件委托给父元素,这样减少了多个事件侦听,通过
一个事件侦听执行所有子元素事件问题,当使用事件委托时,就可以
不再使用e.stopPropagation();阻止冒泡了,因为只执行了最后一层函数(最上面一层)
var ul = document.querySelector('ul')
ul.onclick = function (e) {
if (e.target.nodeName === 'LI') {
console.log(e.target.innerText)
}
}
ul.onclick = function (e) {
if (e.target.nodeName === 'LI') {
console.log(e.target.innerText)
}
}
var btn = document.querySelector('button')
btn.onclick = function () {
ul.innerHTML += '<li>新来的</li>'
}
8.This指向
this 指向
+ 指向: 指引用地址的方向
+ 表达: this 到底是什么
+ 需要结合上下文, 决定不同位置的 this 指向的内容不一样
this 是一个关键字(熟读并背诵全文, 手抄)
+ 是一个使用在作用域内的关键字
=> 要么用在全局
-> 因为在全局使用 this 的时候
-> this 指向 window
=> 要么用在函数内
+ 函数内的 this (this只看函数调用 哪个函数里的this就看哪个函数)
=> 重点: 不管函数定义在哪, 不管函数怎么定义, 只看函数如何被调用(箭头函数除外)
=> 普通调用
-> 函数名()
-> this 指向 window
=> 对象调用
-> 对象名.函数名()
-> this 指向 对象(点前面是谁就是谁)
=> 定时器调用
-> setTimeout(函数, 数字)
-> setInterval(函数, 数字)
-> this 指向 window
=> 事件处理函数
-> 事件源.on事件类型 = 函数
-> 事件源.addEventListener(事件类型, 函数)
-> this 指向 事件源
=> 未完待续 ...
function fn() {
console.log('fn 函数内的打印信息')
console.log('this : ', this)
console.log('------------------------------')
}
var obj = {
name: '我是 obj 对象',
f: fn
}
obj.f()
var btn = document.querySelector('button')
btn.onclick = obj.f
setTimeout(fn, 2000)
9. on事件和addEventListener事件区别
1、只有系统事件使用on 不能自定义事件
2、on事件可以在标签上定义,但是不能通过标签中传事件参数
3、onclick只能赋值一个函数,如果赋值多个函数会被替换,addEventListener可以侦听多次
4、大多数的on事件函数都是匿名函数,造成同一个函数不能复用,不能抽象出来
10.Event事件(记)
change
error
load
reset
resize
select
submit
scroll
1.change 可以针对表单元素,也可以针对表单
修改触发事件
例:
var form=document.querySelector("form");
var input=document.querySelector("input");
var radio=document.querySelector("[type=radio]");
form.addEventListener("change",changeHandler);
function changeHandler(e){
console.log(e)
}
2.select 选择,文本框选择
文本框中文本被选中时
例:
var input=document.querySelector("input");
input.addEventListener("select",selectHandler);
function selectHandler(e){
console.log(input.selectionStart,input.selectionEnd)
console.log(e)
}
3. submit 提交
reset 重置
针对form表单
例:
var form=document.querySelector("form");
form.addEventListener("submit",submitHandler);
form.addEventListener("reset",submitHandler);
function submitHandler(e){
e.preventDefault();
console.log(e)
}
4. resize 用于window对象 缩放事件
rem em
window.addEventListener("resize",resizeHandler);
例:
function resizeHandler(e){
document.documentElement.style.fontSize=document.documentElement.clientWidth/screen.width*100+"px"
}
5. load 加载
error 加载错误
预加载案例
6. scroll 滚动条事件
window document
所有的可以设置 overflow: scroll;的容器都可以增加这个事件
例:
document.addEventListener("scroll",scrollHandler);
function scrollHandler(e){
console.log("aa")
}
10.1 案例-预加载