最新更新时间:2019年2月14日10:45:54
《猛戳-查看我的博客地图-总有你意想不到的惊喜》
本文内容:DOM原生事件、DOM自定义事件、事件处理程序、事件对象、react事件
事件
JavaScript与HTML的交互是通过事件完成的,事件流模型包括:事件冒泡和事件捕获
事件冒泡
IE事件流叫做事件冒泡(event bubbling),即事件由最具体的元素向上传播到顶层对象。
- IE9、Firefox、Chrome和Safari将事件一直冒泡到window对象
事件捕获
IE事件流叫做事件冒泡(event capturing),即事件由顶层对象向下传播到最具体的元素。
- IE9、Firefox、Chrome和Safari将事件一直冒泡到window对象
事件处理程序(事件侦听器)
响应某个事件的函数
事件处理程序的形式
HTML事件处理程序
//形式一
<input type='button' value='i am button' onclick="console.log(123)" />
//形式二
<input type='button' value='i am button' onclick="print()" />
function print(){
console.log(123)
}
DOM0级事件处理程序
<input id='btn' type='button' value='i am button' />
var btn = document.getElementById('btn');
btn.onclick = function(){
console.log(123)
}
//删除事件处理程序
btn.onclick = null;
DOM2级事件处理程序-w3c规范
<input id='btn' type='button' value='i am button' />
var btn = document.getElementById('btn');
btn.addEventListener('click', handler, false);//arguments[2] true-捕获阶段调用事件处理程序 false-冒泡阶段调用事件处理程序
function handler(){
console.log(123)
}
btn.addEventListener('click', function(){
console.log(456)
}, false);
//移除事件
btn.removeEventListener('click', handler, false);//btn第二次添加的匿名函数事件无法移除
DOM2级事件处理程序优点:可以为一个元素添加多个事件处理程序
DOM2级事件处理程序-IE规范
<input id='btn' type='button' value='i am button' />
var btn = document.getElementById('btn');
//注意:事件明多了on
btn.attachEvent('onclick', handler);//没有arguments[2] 由于IE8及更早版本只支持事件冒泡,所以attachEvent添加的时间处理程序都会被添加到冒泡阶段。
function handler(){
console.log(123)//attachEvent定义事件的情况下 this === window true
}
//移除事件
btn.detachEvent('click', handler, false);//btn第二次添加的匿名函数事件无法移除
跨浏览器的事件处理程序
var EventUtil = {
addHandler: function(element, type, handler){
if(element.addEventListener){
element.addEventListener(type, handler, false)//w3c DOM2
}else if(element.attachEvent){
element.attachEvent("on" + type, handler)//IE DOM2
}else{
element.['on' + type] = handler//DOM0
}
},
removeHandler: function(element, type, handler){
if(element.removeEventListener){
element.removeEventListener(type, handler, false)
}else if(element.datachEvent){
element.datachEvent("on" + type, handler)
}else{
element.['on' + type] = null
}
},
//跨浏览器的事件对象,DOM中的event和IE中的event
getEvent: function(event){
return event ? event : window.event;
},
getTarget: function(event){
return event.target || event.srcElement;
},
preventDefault: function(event){
if(event.preventDefault){
event.preventDefault();
}esle{
event.returnValue = false;
}
},
stopPropagetion: function(event){
if(event.stopPropagetion){
event.stopPropagetion();
}esle{
event.cancelBubble = true;
}
}
}
事件对象:DOM中的event和IE中的event
//w3c event 对象属性全是只读不可写的
var event = {
bubbles: true | flase,//事件是否冒泡
cancelable: true | flase,//是否可以取消事件默认行为
currentTarget: Element,//当前正在处理的元素
defaultPrevented: true | flase,//true表示已经调用了preventDefault()(DOM3级事件中新增)
detail: Integer,//与事件相关的细节信息
eventPhase: Integer,//调用事件处理程序的阶段:1表示捕获阶段,2表示处于目标阶段,3表示冒泡阶段
preventDefaule(): Function,//取消事件默认行为。如果cancelable为true,则可以使用这个方法
stopImmediatePropagation(): Function,//取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增)
stopPropagetion(): Function,//取消事件的进一步捕获或冒泡,如果bubbles为true,则可以使用这个方法
target: Element,//事件的目标
trusted: true | flase,//true表示事件是浏览器生成的 false表示事件是开发人员通过JavaScript创建的(DOM3级事件中新增)
type: String,//被触发的事件类型
view: AbstractView,//与事件关联的抽象视图,等同于发生事件的window对象
}
//IE event 前两个可读可写,后两个只读不可写
var event = {
cancelable: true | flase,//默认为false,设为false可以取消事件冒泡
returnValue: true | flase,//默认为true,设为false可以取消事件默认行为
srcElement: Element,//事件目标
type: String,//被触发的事件类型
}
取消事件的相关场景
event.preventDefault();//可以阻止a标签链接的默认跳转行为
event.stopPropagetion();//立即停止事件在DOM层级中的传播,即取消进一步的事件捕获或冒泡
//event.eventPhase的三种情况
var btn = document.getElementById('btn');
btn.onclick = function(event){
console.log(event.eventPhase)//2
}
document.body.addEventListener('click',function(event){
console.log(event.eventPhase)//1
},true)
document.body.onclick = function(event){
console.log(event.eventPhase)//3
}
react中的事件
//注册事件的形式:合成事件 原生事件
//原生事件的绑定与销毁
<div ref='parent2' id='parent2' className='parent2' style={{background:'#ff6788',padding: '1rem'}}></div>
componentDidMount(){
document.getElementById('parent2').addEventListener('click',(e)=>{this.parentCallback2(e)})
}
componentWillUnmount(){
document.getElementById('parent2').removeEventListener('click',(e)=>{this.parentCallback2(e)})
}
//合成事件
<div className='child1' onClick={(e) => {this.childCallback1(e)}} style={{background:'red'}}>1</div>
childCallback1(e){
console.log('child1 click');
}
//取消事件的进一步捕获或冒泡,分为两种情况
//在子元素上使用e.stopPropagation()的情况:合成→合成 | 原生→原生 | 原生→合成
childCallback3(e){
e.stopPropagation();
}
//在父元素上做拦截:合成→原生
parentCallback2(e){
if(e.target.id == 'child2' || e.className == "parent2"){e.target.className e.target.nodeName
return
}
}
react中的合成事件和原生事件
执行先后顺序:先执行原生事件,后执行合成事件
import React, { Component } from 'react';
class Demo extends Component {
constructor(props) {
super(props);
this.state = {
}
}
componentWillMount(){
}
componentDidMount(){
//原生事件只能在这个生命周期方法中绑定,因为此时才能获取DOM元素
document.getElementById('parent').addEventListener('click',(e)=>{console.log('原生事件')})
}
componentWillUnmount(){
document.getElementById('parent').removeEventListener('click',(e)=>{console.log('原生事件')})
}
render() {
return (
<div id='parent' onClick={(e) => {console.log('合成事件')}}>这个元素绑定了原生事件和合成事件</div>
);
}
}
export default Demo;
自定义事件
var divDom = document.getElementById('test')
//dom元素添加用户自定义事件,customEvent01为自定义的事件类型
divDom.addEventListener('customEvent01',customFunc)
//dom元素添加click事件
divDom.addEventListener('click',clickFunc)
//触发条件:代码触发
function customFunc(data){
console.log('触发自定义事件customEvent01成功')
console.log(data)
console.log(data.type)//"customEvent01"
}
//触发条件:鼠标单击dom元素
function clickFunc(data){
console.log('触发原生click事件成功')
console.log(data.type)//"click"
}
setTimeout(function(){
//创建自定义事件
var event = new Event("customEvent01");
//用户可自定义添加属性和方法
event.state = 'ok'
event.data = '123';
//触发自定义事件
divDom.dispatchEvent(event);
},3000)
感谢阅读,欢迎评论^-^