• 事件基础,事件绑定,DOM事件流与事件的默认行为,键盘事件,滚轮事件,事件委托(js)


    1、事件基础

    事件是可以被 javaScript 侦测到的行为。 网页中的每个元素都可以产生某些可以触发javaScript函数的事件。比方说,我们可以在用户点击某按钮时产生一个 onclick 事件来触发某个函数。

    1、事件函数

    事件函数:被事件触发的才是事件函数

    var box = document.getElementById('box');
    function fn() { }
    ​
    box.onclick = fn; // fn就是事件函数
    ​
    fn(); // 不是事件函数
    ​
    box.onclick = function () { // 事件函数
        fn(); // 不是事件函数
    }

    2、事件对象

    事件对象:当一个事件发生的时候,跟这个事件有关的一些详细信息,被保存在一个对象中,这个对象,就是事件对象

    • IE和谷歌:全局的event对象

    • 标准浏览器:事件函数的第一个参数

    • 兼容:var ev = ev || event;

    var box = document.getElementById('box');
    ​
    box.onclick = function (ev) {
        // console.log(event); // IE和谷歌支持
        // console.log(ev); // 标准浏览器支持
        var ev = ev || event; // 事件对象的兼容
    ​
        console.log(ev.type); // 事件类型
        // console.log(ev.target); // 事件源 标准浏览器支持
        // console.log(ev.srcElement); // 事件源 IE8及以下
        var target = ev.target || ev.srcElement; // 事件源的兼容
        target.style.backgroundColor = 'green';
    ​
        console.log(ev.clientX, ev.clientY); // 鼠标相对可视区的位置
        console.log(ev.pageX, ev.pageY); // 鼠标相对文档的距离 IE8及以下没有
        console.log(ev.shiftKey); // 这个事件发生的时候,shift键是否按下
        console.log(ev.ctrlKey); // 这个事件发生的时候,ctrl键是否按下
        console.log(ev.altKey); // 这个事件发生的时候,alt键是否按下
    }

    2、事件的绑定

    需求:给同一个元素的同一个事件绑定不同的处理函数

    var box = document.getElementById('box');
    function fn1() {
        console.log(1);
        // console.log(this === window);
    }
    function fn2() {
        console.log(2);
    }
    
    // 这种写法是一种赋值的写法,后面的会覆盖前面的
    box.onclick = fn1;
    box.onclick = fn2;
    
    // 标准浏览器支持
    // 元素.addEventListener(不要on的事件名, 函数, 是否捕获);
    // 是否捕获:如果不写,默认false
    box.addEventListener('click', fn1, false);
    box.addEventListener('click', fn2, false);
    
    // IE8及以下支持
    // 元素.attachEvent(要on的事件名, 函数);
    box.attachEvent('onclick', fn1);
    box.attachEvent('onclick', fn2);
    
    // addEventListener和attachEvent的区别:
    1、标准事件名不要on,而非标准要on
    2、标准的可以捕获,而非标准没有捕获
    3、标准的是顺序执行,而非标准是倒序执行
    4、标准执行的函数中的this是触发这个函数的元素,而非标准执行的函数中的this是window
    
    // 事件绑定的封装的原理
    console.log(box.addEventListener); // 在标准浏览器下返回一个函数,在IE8及以下返回undefined
    // 封装 参数:元素 事件 函数
    function bind(ele, event, callback) {
        if (ele.addEventListener) {
            // 标准浏览器
            ele.addEventListener(event, callback, false);
        } else {
            // IE8及以下
            ele.attachEvent('on' + event, callback);
        }
    }
    ​
    bind(box, 'click', fn1);
    bind(box, 'click', fn2);

    事件的取消:

    // 这种写法是一种赋值的写法,后面的会覆盖前面的
    box.onclick = fn1;
    box.onclick = fn2;
    box.onclick = null; // 取消
    
    // 标准浏览器支持
    // 元素.addEventListener(不要on的事件名, 函数, 是否捕获);
    // 元素.removeEventListener(不要on的事件名, 函数, 是否捕获);
    // 是否捕获:如果不写,默认false
    box.addEventListener('click', fn1, false);
    box.addEventListener('click', fn2, false);
    box.removeEventListener('click', fn2, false); // 取消
    
    // IE8及以下支持
    // 元素.attachEvent(要on的事件名, 函数);
    // 元素.detachEvent(要on的事件名, 函数);
    box.attachEvent('onclick', fn1);
    box.attachEvent('onclick', fn2);
    box.detachEvent('onclick', fn2); // 取消
    
    // 事件绑定封装 参数:元素 事件 函数
    function bind(ele, event, callback) {
        if (ele.addEventListener) {
            // 标准浏览器
            ele.addEventListener(event, callback, false);
        } else {
            // IE8及以下
            ele.attachEvent('on' + event, callback);
        }
    }
    // 事件取消封装 参数:元素 事件 函数
    function unbind(ele, event, callback) {
        if (ele.removeEventListener) {
            // 标准浏览器
            ele.removeEventListener(event, callback, false);
        } else {
            // IE8及以下
            ele.detachEvent('on' + event, callback);
        }
    }
    ​
    bind(box, 'click', fn1);
    bind(box, 'click', fn2);
    unbind(box, 'click', fn2); // 取消

    3、DOM事件流

    1、事件流

    分为三个阶段

    1、捕获阶段:从最外面不具体的元素,到最具体的元素。document - html - body - box1 - box2 - box3

    2、处于目标阶段

    3、冒泡阶段:从最里面具体的元素,到最外面不具体的元素。box3 - box2 - box1 - body - html - document

    • 当经过某个元素时,同时这个元素上面也绑定着事件,哪这个事件就会被触发

    • 如果要捕获,就必须addEventListener绑定,而冒泡是默认存在的,即"元素.事件"和"attacheEvent"这种绑定都只有冒泡

     

    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    
    var box1 = document.getElementById('box1');
    var box2 = document.getElementById('box2');
    var box3 = document.getElementById('box3');
    ​
    // 元素.事件 = 函数; 这种方式只能冒泡触发 (冒泡是默认存在的)
    box1.onclick = function () {
        console.log(1);
    }
    box2.onclick = function () {
        console.log(2);
    }
    box3.onclick = function () {
        console.log(3);
    }
    ​
    // --------------------
    // 第三个参数为true,则是捕获触发
    box1.addEventListener('click', function () {
        console.log(1);
    }, true);
    box2.addEventListener('click', function () {
        console.log(2);
    }, true);
    box3.addEventListener('click', function () {
        console.log(3);
    }, true);
    ​
    box1.addEventListener('click', function () {
        console.log(1);
    }, false);
    box2.addEventListener('click', function () {
        console.log(2);
    }, false);
    box3.addEventListener('click', function () {
        console.log(3);
    }, false);

    2、阻止事件冒泡

    • 标准浏览器:ev.stopPropagation();

    • IE浏览器:ev.cancelBubble = true;

    // 阻止冒泡的兼容
    function stopPropagation(ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation();
        } else {
            ev.cancelBubble = true;
        }
    }

    二级菜单

    var btn = document.getElementsByTagName('button')[0];
    var box = document.getElementById('box');
    ​
    btn.onclick = function (ev) {
        var ev = ev || event;
        box.style.display = 'block';
    ​
        // 阻止冒泡
        // ev.stopPropagation(); // 标准浏览器
        // ev.cancelBubble = true; // IE8及以下
        stopPropagation(ev); // 兼容
    }
    ​
    // 点页面其它的地方,document
    document.onclick = function () {
        box.style.display = 'none';
    }
    ​
    // 阻止冒泡的兼容
    function stopPropagation(ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation();
        } else {
            ev.cancelBubble = true;
        }
    }
     

    4、事件的默认行为

    事件的默认行为,即赋予了元素特殊的操作,如点击链接会跳转到其他的网页,在浏览器中右击鼠标会弹出菜单,当我们不需要这些默认行为的时候,可以手动阻止

    • 标准:ev.preventDefault();

    • IE8及以下:ev.returnValue = false;

    var a = document.getElementsByTagName('a')[0];
    a.onclick = function (ev) {
        var ev = ev || event;
    ​
        // ev.preventDefault();
        // ev.returnValue = false;
        preventDefault(ev);
    }
    ​
    function preventDefault(ev) {
        if (ev.preventDefault) {
            ev.preventDefault();
        } else {
            ev.returnValue = false;
        }
    }

    案例:自定义右键菜单

    5、键盘事件

    • onkeydown代表键盘被按下

    • onkeyup代表键盘被抬起

    • oninput 只要内容发生变化就触发

    键盘事件只能加给能响应键盘输入的元素,能响应键盘输入的元素有:input textarea document...

    var input = document.querySelector('input');
    ​
    // 按着不动,会连续触发
    input.onkeydown = function () {
        console.log(this.value);
    }
    ​
    // 按着不动,只有最后一次抬起触发
    input.onkeyup = function () {
        console.log(this.value);
    }
    ​
    // 集合它俩的优点(IE8及以下不支持)
    input.oninput = function () {
        console.log(this.value);
    }
    
    // 键盘事件的事件对象
    input.onkeydown = function (ev) {
        var ev = ev || event;
        // console.log(ev); // 事件对象
    // console.log(ev.key); // 具体的按键(IE8及以下不支持)
        console.log(ev.keyCode); // 按键对应的编码   
        // a:65  z:90   空格:32  esc:27  回车:13
        // 左键 37 上键38 右键39 下键40
    }

    案例:方向键控制div的移动

    6、滚轮事件

    滚轮事件和滚轮方向

    // 标准和IE
    // 事件:onmousewheel
    // 方向:ev.wheelDelta  上120,下-120
    box.onmousewheel = function (ev) {
        var ev = ev || event;
        console.log(ev.wheelDelta);
    }
    ​
    // 火狐
    // 事件:DOMMouseScroll   而且,必须要用addEventListener绑定
    // 方向:ev.detail  上-3 下3
    box.addEventListener('DOMMouseScroll', function (ev) {
        console.log(ev.detail);
    }, false)
     

    滚轮方向兼容

    // 向上:120  向下:-120
    function wheelDelta(ev) {
        if (ev.wheelDelta) {
            // 标准和IE
            return ev.wheelDelta; // 上120 下-120
        } else {
            // 火狐
            return ev.detail * -40; // 上-3 下3
        }
    }
     

    完整案例实现

    var box = document.getElementById('box');
    ​
    function fn(ev) {
        var ev = ev || event;
        var h = box.clientHeight; // 盒子的高
        var w = box.clientWidth; // 盒子的宽
    if (wheelDelta(ev) > 0) {
            // console.log('向上');
            h--;
            w--;
        } else {
            // console.log('向下');
            h++
            w++;
        }
    ​
        box.style.height = h + 'px';
        box.style.width = w + 'px';
    }
    ​
    bind(box, 'mousewheel', fn); // 标准和IE
    bind(box, 'DOMMouseScroll', fn); // 火狐
    // 向上:120  向下:-120
    function wheelDelta(ev) {
        if (ev.wheelDelta) {
            // 标准和IE
            return ev.wheelDelta; // 上120 下-120
        } else {
            // 火狐
            return ev.detail * -40; // 上-3 下3
        }
    }
    ​
    // 封装 参数:元素 事件 函数
    function bind(ele, event, callback) {
        if (ele.addEventListener) {
            // 标准浏览器
            ele.addEventListener(event, callback, false);
        } else {
            // IE8及以下
            ele.attachEvent('on' + event, callback);
        }
    }
     

    7、事件委托

    什么叫事件委托?它还有一个名字叫事件代理,从JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

    事件委托原理:利用冒泡的原理,把事件加给父级,在触发事件时,找到事件源,判断事件源,做相应的操作

    <ul>
        <li>吃饭</li>
        <li>睡觉</li>
        <li>打篮球</li>
    </ul>
    
    var ul = document.querySelector('ul');
    var li = ul.querySelectorAll('li'); // 只有原来的三个,原来的三个会有事件
    var item = document.createElement('li'); // 新加的一个
    item.innerHTML = '平头哥';
    ul.appendChild(item);
    ​
    ​
    // 给li绑定点击事件,点击时,让li的背景变红
    // 问题:
    // 1、新加的元素没有之前的事件
    // 2、添加多个会消耗内存
    // for (var i = 0; i < li.length; i++) {
    //     li[i].onclick = function () {
    //         this.style.backgroundColor = 'red';
    //     }
    // }
    // -------------------------------
    // 事件委托
    // 1、新加的元素,也有之前的事件
    // 2、提高了性能
    ul.onclick = function (ev) {
        var ev = ev || event;
        var target = ev.target || ev.srcElement;
        // console.log(target); // 事件源
        // console.log(target.nodeName); // 点击元素的标签名
        if (target.nodeName === 'LI') {
            target.style.background = 'yellow';
        }
    }



  • 相关阅读:
    统计代码行数
    梯度下降算法
    multiplot 安装与配置
    ros 源码安装
    cmake 指定gcc/g++版本
    python 科学计算基础库安装
    协方差矩阵的含义
    pysvn 相关
    void 0与undefined
    BEM规范
  • 原文地址:https://www.cnblogs.com/cyf666cool/p/13702709.html
Copyright © 2020-2023  润新知