13-JavaScript-DOM事件

JavaScript中有许多DOM事件


添加事件的方法

  • 通过onXXX的方式来添加
    //1.使用onXXX添加事件
    oBtn.onclick = function () {
        alert("11");
    };
    //同一个元素添加相同的事件后添加的会覆盖前面添加的事件
    oBtn.onclick = function () {
        alert("22");
    };

注意点: 由于是添加给了属性, 所以后赋值的会覆盖先赋值

  • 通过addEventListener方法添加(IE9以上)
    //2.使用addEventListener添加事件
    oBtn.addEventListener("click",function () {
        alert("11");
    });
    //后添加的不会覆盖先添加的
    oBtn.addEventListener("click",function () {
        alert("22");
    })

注意点:
1.事件名称不需要添加on
2.后添加的不会覆盖先添加的
3.只支持最新的浏览器IE9

  • 通过attachEvent方法添加(低版本浏览器)
    //attachEvent只支持低版本浏览器
    //兼容性处理
    function addEvent(ele,name,fn) {
        //兼容低版本浏览器
        if (ele.attachEvent) {
            ele.attachEvent("on"+ name,fn);
        }else {
            ele.addEventListener(name,fn);
        }
    }

注意点:
1.事件名称必须加上on
2.后添加的不会覆盖先添加的
3.只支持低版本的浏览器

点击事件

  • 格式:元素.onclick = function(){};
    当调用者被点击的时候, 就会执行后面赋值的这个函数
oDiv.onclick = function () {
    alert("haha");
}

注意点:
如果是给a标签添加点击事件, 由于a标签对点击事件有默认的实现(跳转)
所以需要注意的是我们添加的点击事件不会覆盖掉系统默认的点击事件
如果不想使用系统的默认事件, 那么只需要在我们添加的函数中return false即可

var oA = document.querySelector("a");
oA.onclick = function () {
     alert("hehe");
     return false;
}

移入移出事件

  • 鼠标移入事件
    onmouseover作用: 监听鼠标移入元素
    onmouseenter作用: 监听鼠标移入元素
  • 鼠标移出事件
    onmousout作用: 监听鼠标移出元素
    onmousleave作用: 监听鼠标移出元素

注意点:
添加鼠标移入事件建议使用onmouseenter
添加鼠标移出事件建议使用onmousleave

注意点:
onmouseover和onmouseenter的区别
onmouseover移入到子元素,父元素也会被触发
onmouseenter移入到子元素,父元素不会被触发
onmouseout和onmouseleave
onmouseout移出到子元素,父元素也会被触发
onmouseleave移出到子元素,父元素不会被触发


焦点事件

  • 监听元素获取焦点
    var oInput = document.querySelector("input");
    // 1.监听元素获取焦点
    oInput.onfocus = function () {
        console.log("onfocus");
    };
  • 监听元素失去焦点
// 2.监听元素失去焦点
    oInput.onblur = function () {
        console.log("onblur");
    };
  • 监听元素内容改变
oInput.onchange = function () {
      console.log(this.value);
}

注意点:
onchange事件不能时时获取数据的改变
onchange事件只有失去焦点的时候才会执行

  • 实时获取元素内容改变
oInput.oninput = function () {
      console.log(this.value);
}

注意点:
oninput事件可以时时获取数据的改变, 但是有兼容性问题,IE9才能使用

// 时时监听输入框内容改变的兼容性处理
function inputChange(ele, fn) {
      if("oninput" in ele){
            ele.oninput = fn;
      }else{
          ele.onpropertychange = fn;
      }
}

闭包

  • 什么是闭包?
    只要函数中用到了其它函数的变量, 这个函数就是一个闭包
  • 闭包有什么特点?
    只要闭包还在使用外界的变量, 那么外界的变量就会一直存在
    function test() {
        var num = 123;
        return function () {
            // 在这个函数中, 用到其它函数的变量
            console.log(num);
        }
    }
    var fn = test();
    fn();

同步和异步

  • 什么是同步?
    只有前面的执行完了, 后面的才能执行,默认情况下, 编写的代码都是同步的
    // 只有i加到10才不满足条件, 所以循环执行完毕i=10
    for (var i = 0; i < 10; i++) {
        function test() {
            console.log(i);
        }
    }
    // 当函数调用时循环已经执行完毕了, 所以拿到的是10
    test();
  • 什么是异步?
    随时可以执行
for (var i = 0; i < 10; i++) {
      (function (index) {
          console.log(index);
      })(i);
}

高级排他实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .selected{
            background: red;
        }
    </style>
</head>
<body>
<ul>
    <li class="selected">我是第1个li</li>
    <li>我是第2个li</li>
    <li>我是第3个li</li>
    <li>我是第4个li</li>
    <li>我是第5个li</li>
</ul>
<script>
    var oLis = document.querySelectorAll("ul>li");
    //利用闭包实现高级排他
    //定义变量保存索引
    var curIndex = 0;
    //遍历所有li标签
    for (var i = 0, len = oLis.length; i < len; i++){
        // 保证立即执行函数中的index和当前循环的i同步
        (function (index) {
            oLis[index].onmouseenter = function () {
                //清除curIndex索引对应的样式
                oLis[curIndex].className = "";
                //给index对应索引添加样式
                oLis[index].className = "selected";
                //保存添加样式的索引值
                curIndex = index;
            }
        })(i);
    }
</script>
</body>
</html>

定时器

  • JavaScript中常用的有两种定时器
    反复执行的定时器
    只执行一次的定时器
  • 反复执行的定时器
    第一个参数: 到指定事件之后执行的回调函数
    第二个参数: 指定间隔的时间
    返回值: 返回当前定时器的ID
    var timerId = null;
    oStartBtn.onclick = function () {
        timerId = setInterval(function () {
            console.log("每个多少毫秒执行一次");
        }, 1000);
  • 只执行一次的定时器
    第一个参数: 到指定事件之后执行的回调函数
    第二个参数: 指定间隔的时间
    返回值: 返回当前定时器的ID
timerId = setTimeout(function () {
      console.log("多少毫秒之后执行一次");
}, 1000);
  • 清除定时器
oEndBtn.onclick = function () {
      clearInterval(timerId);
      clearTimeout(timerId);
}

注意点:
开启定时器之前,一般要先清除定时器,这样可以避免重复开启定时器引发的bug


时间计算

    // 1.获取到当前的时间
    var now = new Date();
    // console.log(now);
    // 可以通过valueOf方法获取调用者距离1970/1/1相差的毫秒
    // console.log(now.valueOf());

    // 2.创建一个指定的时间
    var date = new Date("2018/11/11 23:59:59");
    // console.log(date.valueOf());

    // 需求: 要求计算当前时间距离指定时间相差的天数/小时/分钟/秒钟
    // 3.计算当前时间距离未来时间的毫秒
    // 注意点: 时间对象可以直接进行算数运算, 系统会自动调用valueOf方法
    var time = date - now;
    console.log(time);

    // 将获取到的相差的毫秒转换为秒
    var allSecond = time / 1000;
    console.log(allSecond);

    // 计算天数
    var d = parseInt(allSecond / (60 * 60 * 24));
    console.log(d);

    //计算小时数
    // 计算小时
    //       allSecond / (60 * 60) == 计算总共相差的小时
    //       %24   == 计算除开天数之后相差的小时
    var h = allSecond / (60 * 60) % 24;
    console.log(h);

    // 计算分钟
    //       allSecond / 60  == 计算总共相差的分钟
    //       %60  === 计算除开天数和小时相差的分钟

    var m = allSecond / 60 % 60;
    console.log(m);

    // 计算秒钟
    var s = allSecond % 60;
    console.log(s);

函数节流

  • 什么是函数节流?
    函数节流就是降低性能消耗, 将频繁调用的函数修改为间隔多长时间调用一次
    var oInput = document.querySelector("input");
    // 2.时时监听input内容的变化
    var timerId = null;
    inputChange(oInput, function () {
        var self = this;
        clearTimeout(timerId);
        // console.log("发送一次请求到服务器", this.value);
        //使用一次性定时器,延迟获取输入框内容的请求
        timerId = setTimeout(function () {
            console.log("发送一次请求到服务器", self.value);
        }, 1000);
    });
    function inputChange(ele, fn) {
        if("oninput" in ele){
            ele.oninput = fn;
        }else{
            ele.onpropertychange = fn;
        }
    }

事件对象

  • 什么是事件对象?
    当注册的事件被触发的时候, 系统就会自动创建一个事件对象, 并且返回给我们,事件对象就是一个系统自动创建的对象

注意点:
在高级版本的浏览器中, 会自动将事件对象传递给回调函数
在低级版本的浏览器中, 不会自动将事件对象传递给回调函数
在低级版本的浏览器中, 需要通过window.event来获取事件对象

//兼容低版本浏览器写法
event = event || window.event;
  • 阻止默认元素默认事件的三种方法
// 1.企业开发推荐
return false;
// 2.禁用默认行为
// 注意点: 高级版本浏览器支持
event.preventDefault();
event.returnValue = false; // 老版本IE

事件传递阶段

  • 事件的三个阶段
    1.捕获阶段 (从外向内)
    2.当前目标阶段
    3.冒泡的阶段 (从内向外)

注意点:
事件的状态只有两种,要么捕获和当前,要么当前和冒泡

  • 如何设置事件到底是捕获还是冒泡?
    需要通过addEventListener方法
    因为这个方法接收三个参数
    第一个参数: 事件的名称
    第二个参数: 回调函数
    第三个参数: false冒泡 / true 捕获
    var oBox = document.querySelector(".box");
    var oFDiv = document.querySelector(".father");
    var oSDiv = document.querySelector(".son");
    oBox.addEventListener("click", function (event) {
        event = event || window.event;
        console.log(event.eventPhase, "box");
    }, false);

    oFDiv.addEventListener("click", function (event) {
        event = event || window.event;
        console.log(event.eventPhase, "father");
    }, false);

    oSDiv.addEventListener("click", function () {
        console.log(event.eventPhase, "son");
    }, false);

注意点:
onXXXX的属性, 不接收任何参数, 所以默认就是冒泡
attachEvent方法, 只能接收两个参数, 所以默认就是冒泡
所以如果想指定为捕获, 只能使用addEventListener方法

  • 阻止事件冒泡方法
// 阻止事件冒泡,给哪个事件添加哪个事件就会阻止冒泡
// 适用于高级版本的浏览器
event.stopPropagation();
// 适用于低级版本的浏览器
event.cancelBubble = true;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343