DOM的事件操作

158 阅读2分钟

获取滚动条滚动的距离

window.pageXOffset
window.pageYOffset
IE8IE8以下的浏览器:
document.body.scrollLeft/Top
document.documentElement.scrollLeft/Top
它两有一个特性,兼容性特别不好,哪个适用哪个浏览器
是混乱的,但这个版本的浏览器适用其中一个,另一个就
为 0;
因此,如果要兼容他们:
(document.body.scrollLeft + document.documentElement.scrollLeft)
 封装兼容性方法,求滚动条滚动距离getScrollOffset();
    function getScrollOffset() {
        if(window.pageXOffset){
            return {
                x: window.pageXOffset,
                y: window.pageYOffset
            }
        }else{
            return {
                x: document.body.scrollLeft + document.
                    documentElement.scrollLeft,
                y: document.body.scrollTop + document.
                    documentElement.scrollTop
            }
        }
    }

浏览器可视窗口的尺寸

    1、定义:就是我们编写能看见的html文档部分

    2、标准方法:IE8IE8以下不兼容
        window.innerWidth
        window.innerHeight

    3IE8IE8以下:
        标准模式下:<!DOCTYPE html>
            document.documentElement.clientWidth/clientHeight
        怪异模式下:没有<!DOCTYPE html>就是怪异模式
            document.body.clientWidth/clientHeight
        
            如何查看文档是标准模式,还是混合模式
            // 标准模式
            document.compatMode === "CSS1Compat"

            // 混合模式/怪异模式
            document.compatMode === "backCompat"
    
    4、封装兼容性方法,返回浏览器视口尺寸getViewportOffset();
        
        function getViewprotOffset() {
            if(window.innerWidth){
                return {
                    w: window.innerWidth,
                    h: window.innerHeight
                }
            }else{
                if(document.compatMode === "backCompat"){
                    // 判断是标准模式还是混合模式
                    return {
                        w: document.body.clientWidth,
                        h: document.body.clientHeight
                    }
                }else{
                    return {
                        w: document.documentElement.clientWidth,
                        h: document.documentElement.clientHeight
                    }
                }
            }
        }

获取元素的尺寸及位置

    1、查看元素的尺寸
        // 包括padding和border
        dom.offsetWidth
        dom.offsetHeight

    2、查看元素的位置
        // 是相对于最近有定位元素的父级进行定位距离
        // (与自己的内容区域),没有就相对于文档
        dom.offsetLeft
        dom.offsetTop

    3、dom.offsetParent; // 查看自己最近的有定位的父级

让滚动条滚动

    1、window上有三个方法
        (1)scroll(x, y);  // 能让滚动条滚动到某个位置2scrollTo(); // 和srcoll()功能一样3scrollBy(x, y)
            // 让滚动条滚动距离是累加的,执行一次就多滚动
            // 多少距离

获取鼠标点击的位置

elem.onclick = function(e) {
    var x = e.pageX
    var y = e.pageY
}

事件绑定及解除

一、事件:一旦事件绑定在循环里面,就要考虑是否会触发闭包
        触发闭包,可以通过立即执行函数解决
        
        var li = document.getElementsByTagName('li');
        var len = li.length;
        for(var i = 0; i < len; i ++){
            (function (j) {
                li[j].addEventListener('click', function () {
                    console.log(j);
                }, false)
            }(i))

        }
    1、事件:是实现交互体验的核心功能
        (1)dom.onclick = function () {}
            都适用兼容性好

        (2)dom.addEventListener(事件, function () {
                // 事件触发执行体,多个事件监听,就可以执行多次,不管一不一样
            }, false)

            // IE9以下不兼容3)dom.attachEvent('on' + 事件, function () {
                // 事件触发执行体
            })
            // IE独有

    2、事件运行环境问题:this1)dom.onclick = function () {
            console.log(this);  // 输出dom自己
        }

    (2)dom.addEventListener('click', function () {
            console.log(this); // 输出 dom自己
        }, false);

    (3)dom.attachEvent('onclick', function () {
            console.log(this); // 输出 window
        })

        // 只有这个特殊,解决办法:利用call/apply改变this指向
        dom.attachEvent('onclick', function () {
            handle.call(dom);
        });
        function handle() {
            // 事件处理程序
            console.log(this); // 这样this就指向dom自己了
        }

    3、封装addEvent(elem, type, handle);方法,让所有的事件都好使
        function addEvent(elem, type, handle) {
            if(elem.addEventListener){
                elem.addEventListener(type, handle, false);
            }else if(elem.attachEvent){
                elem.attachEvent('on' + type, function () {
                    handle.call(elem);
                });
            }else{
                elem['on' + type] = handle;
            }
        }
    

二、事件解除
    1、dom.onclick = function () {}
        // 属性赋值的形式,重新赋值null 就可以解除事件了
        dom.onclick = null;

    2、 dom.addEventListener('click', function () {
           // 如果此处是用匿名函数,那就解除不掉了。
        }, false);

      (1)解除方法:
        function test() {
            // 事件处理函数体写在外面
        }
        // 绑定
        dom.addEventListener('click', test, false);

        // 解除
        dom.removeEventListener('click', test, false);
    
    3、dom.attachEvent('onclick', test); // 绑定事件
       dom.detachEvent('onclick', test); // 解除事件绑定

事件委托

  • 原理:利用事件冒泡机制

      var ulDemo = document.getElementsByTagName('ul')[0];
      ulDemo.onclick = function(e) {
          var event = e || window.event;
          var target = event.target || event.srcElement;
          console.log(target);
      }
    

事件冒泡、事件捕获、默认事件

一、事件处理模型:点击谁,谁就是事件执行
    1、事件冒泡:
        结构上(非视觉上),嵌套关系的元素,会存在事件冒泡
        的功能,即同一事件,自子元素冒泡向父元素。(自里向外)
        通过触发子元素身上的事件,会一层一层往外触发父元素身上的事件
    
    2、事件捕获:
        结构上(非视觉上),嵌套关系的元素,会存在事件冒泡
        的功能,即同一事件,自父元素冒泡向子元素。
        通过触发子元素身上的事件,会被有事件捕获的父元素事件捕获,优先执行有捕获的父元素事件,一层一层向内,没有捕获的按冒泡执行顺序。
        
        (1)只有google chrome 实现了,IE没有捕获事件,
            最新版本的火狐也有

        (2)一个对象的一个事件类型,只能遵循一种事件模型,
            不是冒泡就是捕获
        
        (3)如何触发事件捕获模型:false 变为 true
            将dom.addEventListener('click', function () {

              }, true);

            // 执行顺序和事件冒泡相反,自外向里

        (4)另一种事件捕获:只有ie能用,比较老的正常不用
              dom.setCapture();
              dom.releaseCapture(); // 释放

    3、触发顺序:先捕获,后冒泡。
       事件执行顺序:谁在前,谁先执行

    4、有些特殊事件没有冒泡:
        focus   blur  change   submit  reset  select


二、取消冒泡
    1、有些时候我们并不希望事件冒泡,因为我们对子元素绑定事件
        点击,也会触发父级元素事件。
    
    2、W3C标准 event.stopPropagation();但不支持ie9以下版本
        event.cancelBubble = true; // ie和chrome有

        document.onclick = function () {
            console.log('你闲的呀');
        }
        var div = document.getElementByTagName('div')[0];
        div.onclick = function (e) {
            e.stopPropagation();
        }
    
    3、封装stopBubble(event);实现取消冒泡
        function stopBubble(event) {
            if(event.stopPropagation){
                event.stopPropagation();
            }else{
                event.cancelBubble = true;
            }
        }

        div.onclick = function (e) {
            e.stopBubble();
        }

三、阻止默认事件
    1、默认事件: 表单提交、a标签跳转、右键菜单等

    2、return false;  以对象属性的方式注册的事件才生效;
        document.oncontextmenu = function () {
            console.log('a');
            return false;
        }

        <a href="javascript:void(false)">https://www.baidu.com</a>
        <a href="javascript:;">https://www.baidu.com</a>
        // 协议限定符

    3、event.preventDefault();  W3C标准,IE9以下不兼容

    4、event.returnValue = false;   兼容IE
        document.oncontextmenu = function (e) {
            console.log('a');
            e.returnValue = false;
        }

    5、封装阻止默认事件的函数 cancelHandler(event);
        document.oncontextmenu = function (e) {
            console.log('a');
            cancelHandler(e);
        }
        function cancelHandler(event) {
            if(event.preventDefault) {
                event.preventDefault();
            }else{
                event.returnValue = false;
            }
        }