前端3DOM编程2——DOM事件

目录

1、事件流

2、事件注册与触发

3、事件对象

4、事件分类

5、事件代理


五、DOM事件

事件,是用户或浏览器自身执行的某种动作。当在网页上操作时,比如点击一个DOM元素、键盘按下一个键、输入框输入内容、页面加载完成等,都会触发DOM事件。

1、事件流

DOM事件流即DOM事件处理执行的过程,为了判断页面的哪一部分会拥有特定的事件。W3C对DOM事件流作了规范的定义,主要分为三块内容。

capture phase:捕获过程,从DOM树最顶端window对象开始,往下捕获,直到捕获到触发该事件的节点的父元素。

target phase:目标节点,即事件处理节点的事件触发过程。

bubble phase:冒泡过程,从当前事件节点的父结点开始,冒泡到顶层的window对象。

注册到这个事件流的任意一个节点,都会被触发。

不是所有事件都有这三个过程,有些事件没有冒泡,如页面的node事件。

2、事件注册与触发

主体都是事件对象的DOM元素。

(1)事件注册

eventTarget.addEventListener(type,listener[,useCapture])

参数为事件类型、事件处理函数、是否是捕获过程(可选参数)。默认false处理冒泡过程。

大多数情况下,将事件处理函数添加到事件流的冒泡阶段,可以最大限度地兼容各种浏览器,最好只在需要在事件到达目标之前截获它的时候将事件处理函数添加到捕获阶段。

这里的事件处理函数在其依附元素的作用域中执行。

(2)取消事件注册

eventTarget.removeEventListener(type,listener[,useCapture])

添加的匿名函数无法移除。

(3)事件触发

点击元素、按下按键等都可能触发,使用程序代码触发如下。

eventTarget.dispatchEvent(type)

var elem=document.getElementById('div1');
var clickHandler=function(event){
    //事件处理函数,当事件触发的时候,引擎中调用该函数
}
elem.addEventListener('click',clickHandler,false); //在一个节点可处理多个事件处理函数,先添加先处理
elem.onclick=clickHandler; //冒泡过程,但事件处理函数只有一个

elem.removeEventListener('click',clickHandler,false);
elem.onclick=null; //不建议用这种方式

elem.dispatchEvent('click');

(4)浏览器兼容型(IE8-)

事件的注册与取消attachEvent()/detachEvent(),事件触发fireEvent(e)。没有捕获阶段。

这里的事件处理函数在全局作用域运行,其中的this等于window。且这些事件处理函数以添加它们的相反顺序被触发。

var addEvent=document.addEventListener ?
    function(elem,type,listener,useCapture){
        elem.addEventListener(type,listener,useCapture);
    } :
    function(elem,type,listener,useCapture){
        elem.attachEvent('on'+type,listener);
    };

var delEvent=document.removeEventListener ?
    function(elem,type,listener,useCapture){
        elem.removeEventListener(type,listener,useCapture);
    } :
    function(elem,type,listener,useCapture){
        elem.detachEvent('on'+type,listener);
    };

3、事件对象

当事件被触发时,会调用事件处理函数,调用时引擎会传入对象,包含当前事件状态的信息,这就是事件对象。在IE低版本中,一个事件的event对象不是直接通过函数传入,而是放在window对象上。编程过程中会用到该事件对象的属性和方法。

如当用鼠标点击元素时,触发click事件,调用clickHandler函数,传入event对象,可能包含鼠标的XY坐标、shift是否按下等等。

var elem=document.getElementById('div1');
var clickHandler=function(event){
    event=event||window.event;
    //TO DO
}
addEvent(elem,'click',clickHandler,false); 

事件对象通用的属性和方法。

type:事件类型,对事件处理函数的封装switch-case;

target:事件触发的节点,IE低版本使用srcElement属性;

currentTarget:要处理一个事件时,可以把该事件注册在target或其父节点,currentTarget是注册该事件的节点的元素。只有当事件处于目标阶段,才等于target。

<body>
    <input type="button" id="myBtn" />
</body>
var btn=document.getElementById("myBtn");
btn.onclick=function(event){
    alert(event.currentTarget===this); //true
    alert(event.target===this); //true
}
document.body.onclick=function(event){
    alert(event.currentTarget===this); //true
    alert(this===document.body); //true
    alert(event.target===btn); //true
}

stopPropagation():阻止传播,阻止事件传到父节点。event.cancelBubble=true(IE)。

stopImmediatePropagation():阻止事件传到父节点,并阻止当前节点的后续事件。

preventDefault():阻止默认行为(默认行为:点击链接则打开并转到链接,点击提交表单会跳转,双击一段文字文字被选中等)。event.returnValue=false(IE)。

//省略了css
<div class="father">
    <div class="son"></div>
</div>
<a href="http:www.baidu.com">百度</a>

$(function(){
    $(".father").click(function(){
        alert("father");
    });
    $(".son").click(function(event){
        alert("son");
        //阻止冒泡return false;或
        event.stopPropagation();
    });
    $("a").click(function(event){
        alert("弹出注册框");
        //阻止默认行为return false;或
        event.preventDefault();
    });
});

4、事件分类

(1)MouseEvent鼠标事件

事件类型

说明

元素

是否冒泡

默认事件

click

单击主鼠标按钮或按下回车键

Element

YES

focus/activation

dbclick

双击主鼠标按钮

YES

focus/activation/select

mousedown

按下任意鼠标按钮

YES

drag/scroll/text selection

mouseup

释放鼠标按钮

YES

content menu

mousemove

鼠标在元素内部移动重复触发

YES

None

mouseover

进入元素

YES

None

mouseout

离开元素

YES

None

mouseenter

进入元素

NO

None

mouseleave

离开元素

NO

None

mouseover和mouseout移动到后代元素会触发;mouseenter和mouseleave移动到后代元素上不会触发。

属性:clientX, clientY, screenX, screenY,为了处理位置信息,定义鼠标事件发生时,鼠标在页面上的位置。

ctrlKey, shiftKey, altKey, metaKey(Windows键或Cmd键),当事件被触发时,如果键盘上的键被按下,则对应的属性值为true。

button,属性值为0,1,2,代表按下鼠标左键、中间键或右键。

  

顺序:鼠标事件非常灵敏,会同时触发很多鼠标事件。

从元素A上方移过mousemove->mouseover(A)->mouseenter(A)->mousemove(A)->mouseout(A)->mouseleave(A)

点击元素mousedown->[mousemove]->mouseup->click

//例子--拖拽div,窗体拖动
//忽略了细节,如元素不能被选中,拖动不能超出屏幕范围
<head>
    <style type="text/css">
        #div1{
            position:absolute;top:0;left:0;
            border:1px solid #000;
            width:100px;height:100px;
        }
    </style>
</head>
<body>
    <div id="div1"></div>
    <script>
        var elem=document.getElementById("div1");
        var clientX,clientY,moving;

        //按下鼠标,获取当前位置,moving设为true
        var mouseDownHandler=function(event){
            event=event||window.event;
            clientX=event.clientX;
            clientY=event.clientY;
            moving=!0;
        }

        var mouseMoveHandler=function(event){
            if(!moving) return; //如果moving为false则返回
            event=event||window.event;
            var newClientX=event.clientX,//移动后位置
                newClientY=event.clientY;
            var left=parseInt(elem.style.left)||0,
                top=parseInt(elem.style.top)||0;
            elem.style.left=left+(newClientX-clientX)+'px';//更改元素位置
            elem.style.top=top+(newClientY-clientY)+'px';
            clientX=newClientX;//当前位置
            clientY=newClientY;
        }

        //释放鼠标按钮,moving设为false
        var mouseUpHandler=function(event){
            moving=!1;
        }

        elem.addEventListener('mousedown',mouseDownHandler);
        elem.addEventListener('mousemove',mouseMoveHandler);
        elem.addEventListener('mouseup',mouseUpHandler);
    </script>
</body>

(2)WheelEvent滚轮事件

继承自鼠标事件,拥有其属性和方法。属性:deltaX, deltaY, deltaZ鼠标滚轮在X、Y、Z方向上产生的偏移量;deltaMode指定delta值的单位。

事件类型

说明

元素

是否冒泡

默认事件

wheel

滚动鼠标滚轮或

在垂直方向上滚动页面

Element

YES

scroll or zoom

document

(3)FocusEvent焦点事件

处理元素获得或失去焦点。属性:relatedTarget,一个元素获得焦点必然另一个元素失去焦点,对于focus、focusin,该属性指向失去焦点的元素。

事件类型

说明

元素

是否冒泡

默认事件

focus

获得焦点

Window

Element

NO

None

blur

失去焦点

NO

None

focusin

获得焦点前

NO

None

focusout

失去焦点前

NO

None

(4)InputEvent输入事件

在输入框输入内容时不断触发该事件。onpropertychange(IE)。

事件类型

说明

元素

是否冒泡

默认事件

beforeinput

输入内容前触发

Element

YES

update DOM/Element

input

正在输入不断触发

YES

None

(5)KeyboardEvent键盘事件

事件类型

说明

元素

是否冒泡

默认事件

keydown

按下键

Element

YES

beforeinput/input focus/blur activation

keyup

释放键

YES

None

属性:key按键,值为一个字符串;

code按键,值为一个字符串;

ctrlKey, shiftKey, altKey, metaKey,当事件被触发时,如果键盘上的键被按下,则对应的属性值为true;

repeat长按一个键,值为true;

keyCode, charCode, which获得按键的ASCII码。

(6)UIEvent

指不一定与用户操作有关的事件。多数这些事件与window对象或表单控件相关。

事件

类型

说明

元素

是否

冒泡

默认

事件

元素例子

load

加载完成

Window/Document

/Element

NO

None

window/image/iframe

unload

window退出

NO

None

window

error

加载错误

Window/Element

NO

None

window/image

select

文本被选中

Element

NO

None

input/textarea

abort

退出

Window/Element

NO

None

window/image

resize

修改窗体大小

Window/Element

NO

None

window/iframe

scroll

页面发生滚动

Document/Element

NO/YES

None

document/div

window对象:load页面所有请求都加载完成;unload离开或关闭当前页面;error页面加载出现异常;abort退出。

image元素:load图片加载完成,在该事件中可得知图片的长宽;error图片加载异常,如给图片赋值错误的url地址;abort退出,如图片加载时按esc。

//当src地址加载失败,显示默认图片
<image alt="photo" src="http://www.163.com/photo.jpg"
onerror="this.src='http://www.163.com/default.jpg'"/>

(7)移动设备事件

分为基础事件(PC事件、触摸事件)和手势(触摸事件的组合),触摸事件:touchstart, touchend, touchmove, touchcancel。

因为要支持多指操作,一个指头按下去,浏览器要处理另外一个指头发生组合行为的判断时间,移动端click有300ms的延时,有卡顿感。fastclick即tap,点击后马上触发行为,通过基础事件封装模拟,touchstart和touchend间隔时间短且坐标在小范围内(几像素)发生移动。此外,向左向右滑都可以封装模拟。

5、事件代理

利用事件冒泡,在DOM树中尽可能最高的层次上只指定一个事件处理程序,就可以管理某一类型的所有事件。添加到页面的事件处理程序需要不断与DOM节点交互,每访问一次DOM就会引起浏览器重排,影响页面的整体运行性能,为了高效处理事件,使用事件代理,将多次与DOM的操作减少为一次。

更多细节参考:https://www.cnblogs.com/liugang-vip/p/5616484.html

<ul id="myLinks">
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
</ul>
var list=document.getElementById("myLinks");
EventUtil.addHandler(list,"click",function(event)){
    event=event||window.event;
    var target=event.target||event.srcElement;

    switch(target.id){
        case "goSomewhere":
            location.href="http://www.wrox.com";
            break;
        case "doSomething":
            document.title="I changed the document's title";
            break;
        case "sayHi":
            alert("hi");
            break;
    }
}

对于事件代理,innerHTML修改不会影响事件处理,因为是冒泡到祖先节点进行事件处理。有时新增的子元素也带有事件。

最适合采用事件代理技术的事件包括click、mousedown、mouseup、keydown、keyup和keypress;mouseover和mouseout事件也冒泡,但处理它们并不容易,需要经常计算元素位置;focus、blur本身没有冒泡特性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值