事件的基础理论(38)

DOM事件

 

 * [DOM事件]

 *

 * 1.什么是事件?

 *   事件就是一件事情或者一个行为(对于元素来说,它的很多事件都是天生自带的),只要我们去操作这个元素,就会触发这些行为

 *   “事件就是元素天生自带的行为,我们操作元素,就会触发相关的事件行为”

 *

 * 2.事件绑定:给元素天生自带的事件行为绑定方法,当事件触发,会把对应的方法执行

 *  oBox.οnclick=function(){}

 *

 * 3.元素天生自带的事件?

 *  [鼠标事件]

 *    click:点击 (PC端是点击,移动端的click代表单击[移动端使用click会有300MS延迟的问题])

 *    dblclick:双击

 *    mouseover:鼠标经过

 *    mouseout:鼠标移出

 *    mouseenter:鼠标进入

 *    mouseleave:鼠标离开

 *    mousemove:鼠标移动

 *    mousedown:鼠标按下(鼠标左右键都起作用,它是按下即触发,click是按下抬起才会触发,而且是先把down和up触发,才会触发click)

 *    mouseup:鼠标抬起

 *    mousewheel:鼠标滚轮滚动

 *    ...

 *

 *  [键盘事件]

 *    keydown:键盘按下

 *    keyup:键盘抬起

 *    keypress:和keydown类似,只不过keydown返回的是键盘码,keypress返回的是ASCII码值

 *    input:由于PC端有实体物理键盘,可以监听到键盘的按下和抬起,但是移动端是虚拟的键盘,所以keydown和keyup在大部分手机上都没有,我们使用input事件统一代替他们(内容改变事件)

 *    ...

 *

 *  [表单元素常用的事件]

 *    focus:获取焦点

 *    blur:失去焦点

 *    change:内容改变

 *    ...

 *

 *  [其它常用事件]

 *    load:加载完成

 *    unload

 *    beforeunload

 *    scroll:滚动条滚动事件

 *    resize:大小改变事件  window.οnresize=function(){} 当浏览器窗口大小发生改变,会触发这个事件,执行对应的事情

 *    ...

 *

 *  [移动端手指事件]

 *    [touch:单手指操作]

 *      touchstart:手指按下

 *      touchmove:手指移动

 *      touchend:手指离开

 *      touchcancel:因为意外情况导致手指操作取消

 *

 *    [gesture:多手指操作]

 *      gesturestart:手指按下

 *      gesturechange:手指改变

 *      gestureend:手指离开

 *    ...

 *

 *  [H5中的AUDIO/VIDEO音视频事件]

 *    canplay:可以播放(播放过程中可能出现由于资源没有加载完成,导致的卡顿)

 *    canplaythrough:资源加载完成,可以正常无障碍播放

 *    ...

事件绑定 

 * 事件绑定

 *   [DOM0级事件绑定]

 *     [element].onxxx=function(){}

 *

 *   [DOM2级事件绑定]

 *     [element].addEventListener('xxx',function(){},false);

 *     [element].attachEvent('onxxx',function(){}); [IE6~8]

 *

 * 目的:给当前元素的某个事件绑定方法(不管是基于DOM0还是DOM2),都是为了触发元素的相关行为的时候,能做点事情(也就是把绑定的方法执行);“不仅把方法执行了,而且浏览器还给方法传递了一个实参信息值 ==>这个值就是事件对象”

box.onclick = function (ev) {
    //=>定义一个形参EV用来接收方法执行的时候,浏览器传递的信息值(事件对象:MouseEvent鼠标事件对象、KeyboardEvent键盘事件对象、Event普通事件对象...)
    //=>事件对象中记录了很多属性名和属性值,这些信息中包含了当前操作的基础信息,例如:鼠标点击位置的X/Y轴坐标,鼠标点击的是谁(事件源)等信息

    //[MouseEvent]
    // ev.target:事件源(操作的是哪个元素)
    // ev.clientX / ev.clientY :当前鼠标触发点距离当前窗口左上角的X/Y轴坐标
    // ev.pageX / ev.pageY:当前鼠标触发点距离BODY(第一屏幕)左上角的X/Y轴坐标
    // ev.preventDefault():阻止默认行为
    // ev.stopPropagation():阻止事件的冒泡传播
    // ev.type:当前事件类型

    //[KeyboardEvent]
    // ev.code:当前按键'keyE'
    // ev.key:当前按键'e'
    // ev.which / ev.keyCode:当前按键的键盘码 69
    // let code = ev.which || ev.keyCode;

    //=>常用的键盘码
    /*
     * 左-上-右-下:37-38-39-40
     * Backspace:8
     * Enter:13
     * Space:32
     * Delete:46
     *
     * Shift:16
     * Alt:18
     * Ctrl:17
     * ESC:27
     *
     * F1~F12:112 ~ 123
     * 48~57:数字键
     * 65~90:小写字母
     */
};

tempInp.onkeydown = function (ev) {
    console.log(ev.which);
};
//=>IE6~8
box.onclick = function (ev) {
    //=>在IE低版本浏览器中,浏览器执行绑定的方法,并没有把事件对象传递进来,此时ev===undefined,需要基于window.event来获取(由于是全局属性,鼠标每次操作都会把上一次操作的值替换掉)
    if (!ev) {
        //=>低版本中没有的属性,我们手动设置一下:按照自己有的先获取到值,然后赋值给和标准对应的新属性(经过判断处理后,低版本中也有TARGET/PAGE-X/PAGE-Y这些属性了),后期再使用的时候,直接按照高版本的使用即可
        ev = window.event;
        // console.log(ev.srcElement);//=>ev.srcElement是获取事件源(标准中使用的是ev.target)
        ev.target = ev.srcElement;
        // console.log(ev.pageX);//=>低版本浏览器的事件对象中不存在pageX/pageY
        ev.pageX = ev.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
        ev.pageY = ev.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
        ev.which = ev.keyCode;

        // preventDefault & stopPropagation 这些在低版本下都没有
        ev.preventDefault = function () {
            ev.returnValue = false;//=>低版本阻止默认行为
        };
        ev.stopPropagation = function () {
            ev.cancelBubble = true;//=>低版本阻止冒泡传播
        };
    }
    //=>直接按照高版本的规则来使用即可
    console.log(ev.target, ev.which);
    ev.preventDefault();
    ev.stopPropagation();
};
box.onclick = function (ev) {
    //=>用到谁给谁处理兼容
    ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
};

默认行为及阻止 

 * 事件的默认行为:事件本身就是天生就有的,某些事件触发,即使你没有绑定方法,也会存在一些效果,这些默认的效果就是“事件的默认行为”

 *

 *   A标签的点击操作就存在默认行为

 *     1.页面跳转

 *     2.锚点定位(HASH定位[哈希定位])

 *

 *      <a href="http://www.baidu.com/" target="_blank">

 *          你好世界

 *      </a>

 *      target='_blank':让其在新窗口打开

 *

 *      <a href="#box">hello world</a> 首先会在当前页面URL地址栏末尾设置一个HASH值,浏览器检测到HASH值后,会默认定位到当前页面中ID和HASH相同的盒子的位置(基于HASH值我们还可以实现SPA单页面应用)

 *

 *   INPUT标签也有自己的默认行为

 *      1.输入内容可以呈现到文本框中

 *      2.输入内容的时候会把之前输入的一些信息呈现出来(并不是所有浏览器和所有情况下都有)

 *      ...

 *

 *   SUBMIT按钮也存在默认行为

 *      1.点击按钮页面会刷新

 *      <form action="http://www.zhufengpeixun.cn/">

            <input type="submit" value="提交">

        </form>

        在FORM中设置ACTION,点击SUBMIT,会默认按照ACTION指定的地址进行页面跳转,并且把表单中的信息传递过去(非前后端分离项目中,由服务器进行页面渲染,由其它语言实现数据交互,一般都是这样处理)

 //=>如何阻止默认行为

//1.阻止A标签的默认行为:很多时候我们使用A标签仅仅是想当做一个普通的按钮,点击实现一个功能,不想页面跳转,也不想锚点定位

/*

 * 在结构中阻止

 *   <a href="javascript:;">珠峰培训最新全栈视频,等你来拿~~</a>

 *   javascript:void 0/undefined/null...;

 *

 * 在JS中也可以阻止

 *   给其CLICK事件绑定方法,当我们点击A标签的时候,先触发CLICK事件,其次才会执行自己的默认行为

 */

link.onclick = function (ev) {
    ev = ev || window.event;
    return false;
};

link.onclick = function (ev) {
    ev = ev || window.event;
    ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
};

tempInp.onkeydown = function (ev) {
    // ev = ev || window.event;
    // ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    return false;
};
tempInp.onkeydown = function (ev) {
    ev = ev || window.event;

    let val = this.value.trim(),//=>TRIM去除字符串首位空格(不兼容) this.value=this.value.replace(/^ +| +$/g,'')
        len = val.length;
    if (len >= 6) {
        this.value = val.substr(0, 6);

        //=>阻止默认行为去除特殊按键(DELETE\BACK-SPACE\方向键...)
        let code = ev.which || ev.keyCode;
        if (!/^(46|8|37|38|39|40)$/.test(code)) {
            ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
        }
    }
};

 事件传播机制

* 事件的传播机制

 *   冒泡传播:触发当前元素的某一个事件(点击事件)行为,不仅当前元素事件行为触发,而且其祖先元素的相关事件行为也会依次被触发,这种机制就是“事件的冒泡传播机制”

 * xxx.onxxx=function(){}  DOM0事件绑定,给元素的事件行为绑定方法,这些方法都是在当前元素事件行为的冒泡阶段(或者目标阶段)执行的

 *

 * xxx.addEventListener('xxx',function(){},false)  第三个参数FALSE也是控制绑定的方法在事件传播的冒泡阶段(或者目标阶段)执行;只有第三个参数为TRUE才代表让当前方法在事件传播的捕获阶段触发执行(这种捕获阶段执行没啥实际意义,项目中不用)

 * 不同浏览器对于最外层祖先元素的定义是不一样的

 *    谷歌:window->document->html->body...

 *    IE高:window->html->body...

 *    IE低:html->body...

let aa = null;
document.body.onclick = function(ev) {
    console.log('body', ev, ev === aa); //=>TRUE
};

outer.onclick = function(ev) {
    console.log('outer', ev, ev === aa); //=>TRUE
};

inner.onclick = function(ev) {
    /*ev = ev || window.evenet;
    ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;*/
    aa = ev;
    console.log('inner', ev);
};

* 关于事件对象的一些理解

 *   1.事件对象是用来存储当前本次操作的相关信息,和操作有关,和元素无必然关联

 *   2.当我们基于鼠标或者键盘等操作的时候,浏览器会把本次操作的信息存储起来(标准浏览器存储到默认的内存中(自己找不到),IE低版本存储到window.event中了),存储的值是一个对象(堆内存);操作肯定会触发元素的某个行为,也就会把绑定的方法执行,此时标准浏览器会把之前存储的对象(准确来说是堆内存地址)当做实参传递给每一个执行的方法,所以操作一次,即使再多方法中都有EV,但是存储的值都是一个(本次操作信息的对象而已)

 mouseenter和mouseover的区别

 * mouseeneter 和 mouseover 的区别?

 *   1.over属于滑过(覆盖)事件,从父元素进入到子元素,属于离开了父元素,会触发父元素的out,触发子元素的over

 *     enter属于进入,从父元素进入子元素,并不算离开父元素,不会触发父元素的leave,触发子元素的enter

 *

 *   2.enter和leave阻止了事件的冒泡传播,而over和out还存在冒泡传播的

 *

 * 所以对于父元素嵌套子元素这种情况,使用OVER会发生很多不愿意操作的事情,此时我们使用ENTER会更加简单,操作方便,所以真实项目中ENTER的使用会比OVER多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值