事件(Event)知识整理(二)

 事件流

DOM同时支持两种事件模型:捕获型事件和冒泡型事件
并且每当某一事件发生时,都会经过捕获阶段->处理阶段->冒泡阶段(有些浏览器不支持捕获)

捕获阶段是由上层元素到下层元素的顺序依次。而冒泡阶段则正相反。

如下图

当事件触发时body会先得到有事件发生的信息,然后依次往下传递,直到到达最详细的元素。这就是事件捕获阶段。
还记得事件注册方法ele.addEventListener(type,handler,flag)吧,Flag是一个Boolean值,true表示事件捕捉阶段执行,false表示事件冒泡阶段执行。
接着就是事件冒泡阶段。从下往上 依次执行事件处理函数(当然前提是当前元素为该事件注册了事件句柄)。
在这个过程中,可以阻止事件的冒泡,即停止向上的传递。
阻止冒泡有时是很有必要的,例如

<div onclick=funcA()>
    <button onclick=funcB()>Click</button>
</div>

本意是如果点击div中按钮以外的位置时执行funcA,点击button时执行funcB。但是实际点击button时就会先后执行funcB,funcA。
而如果在button的事件句柄中阻止冒泡的话,div就不会执行事件句柄了。


 拖动事件

①相关拖动事件的触发时机 ☟☟
dragstart:选择当前元素并开始拖动时
drag:拖动当前元素并移动时
dragend:结束对当前元素的拖动(可以是将拖动内容放到其他容器中,也可以是中断拖动)
dragenter: 拖动元素进入当前元素时(区别于dragstart)
dragover: 拖动元素在当前元素上移动时(区别于drag)
dragleave: 拖动元素离开当前元素时(区别于dragover)
drop:有拖动元素被扔进当前元素(当前元素必须是能接受拖动内容的元素,如input:text,textarea...)

②可拖动属性
HTML5中 元素有一个属性draggable(IE10+)。true的时候是可以拖动。false则不可。
图片和链接元素默认是true,其他则都为false。

<img src="hello.png" draggable="false" />
<div draggble="true">Can be dragged</div>

如果拖动元素A(例如一张图片),当光标移动到一个不可放置的元素B(例如另一张图片)时
光标会变成无法拖入的样式(圈圈里面加个反斜线),且不会发生drop事件。
如果重写该元素的dragover和dragenter事件的话,可以改变这种情况。(改变了拖动时光标的样式,并且可以触发drop事件)

var main = document.getElementById("main");
main.ondragover = function() {
    event.returnValue = false;//取消默认行为
}
main.ondragenter = function() {
    event.returnValue = false;
}

 ③dataTransfer对象

在发生上述提及的这些拖动事件时,事件对象都会含有一个储存着拖动的数据的dataTransfer对象。(除此之外的事件是没有这个对象的,例如click,focus)
dataTransfer对象有两个主要方法getData()和setData();
显而易见,这分别是用来获取或设置拖动的数据的方法。但是使用过程中需要传入数据类型的参数。
考虑兼容的话,数据类型目前有两种:"text","URL"。二者的区别只有当拖动内容到另一个浏览器窗口(或新建浏览器的Tab位置)时才会体现出来。
"text"类型不会被特殊处理。"URL"类型则会被当成网页中的链接。
dataTransfer对象的用处:根据需要,开发人员可以在dragstart时用setData()改变拖动数据,或者是在drop时,对getData()获得的数据进行校验。例子:

<input type="text" id="studentID" size=5 maxLength=5/>
<div id="tabA" schoolId="007"></div>
<script>
    var stuId = document.getElementById("studentID");
    stuId.ondrop = function(e){
        e = e || window.event;
        var id = e.dataTransfer.getData("text");
        event.returnValue=!/\D/.test(id);
    }
    /***************************************/
    var tabA = document.querySelector("#tabA");
    tabA.ondragstart=function(){
        e = e || window.event;
        var sid=this.getAttribute("schoolId");
        e.dataTransfer.setData("text",+sid);
    }
</script>

dataTransfer还有两个决定拖动效果的属性:dropEffect,effectAllowed。


 用原生JS写的事件工具类

var EventUtil = function() {
    return {
        //获得事件
        getEvent: function(e) {
            return e || window.event;
        }
        //获得事件源
        , getTarget: function(e) {
            return e.target || e.srcElement;
        }
        //添加事件监听
        , addEvent: function(elem, type, fn) {
            if (elem.attachEvent) {
                elem.attachEvent('on' + type, fn);
            } else if (elem.addEventListener) {
                elem.addEventListener(type, fn, false);
            }
        }
        //移除事件监听
        , removeEvent: function(elem, type, fn) {
            if (elem.detachEvent) {
                elem.detachEvent('on' + type, fn);
            } else if (elem.removeEventListener) {
                elem.removeEventListener(type, fn, false);
            }
        }
        //取消默认行为
        , preventDefault: function(e) {
            if (e.preventDefault) {
                e.preventDefault();
            } else {
                e.returnValue = false;
            }
        }
        //取消冒泡
        , stopPropagation: function(e) {
            if (e.stopPropagation) {
                e.stopPropagation();
            } else {
                e.cancelBubble = true;
            }
        }
    };
}

网页缩放触发resize的问题

平常我们提起resize事件,会想起拖动浏览器边缘,或者点击最大最小化按钮。

而实际上还有另一种情况,就是网页被缩放,无论是Ctrl + mousewheel 还是 通过浏览器的工具栏中的按钮。

缩放的时候,body中其他元素的长宽值不会发生变化,但是页面文档的滚动高度,可视高度会变化(如缩小的时候,看到的内容变小,但是看到的内容量会变大)

document.body.scrollHeight/document.activeElement.scrollHeight

document.body.clientHeight

原文地址:https://www.cnblogs.com/TiestoRay/p/2735711.html