美文网首页
第十五节 JavaScript 事件及事件绑定

第十五节 JavaScript 事件及事件绑定

作者: 心存美好 | 来源:发表于2021-11-26 10:53 被阅读0次

    1. 事件理解

    1.1 什么是事件

    事件是用户或浏览器自身执行的某个动作,诸如点击click,

    JavaScript制作交互效果,离不开事件。所谓的事件,就是用户的某个行为,能够触发一个函数的执行

    1.2 绑定事件绑定:
    oDiv.onclick = function(){
    }
    

    这个匿名函数,平时永远不会执行,必须等到事件的发生才执行。

    响应某个事件的函数叫做事件处理程序,通常我们俗称为事件处理函数,事件的处理程序是以‘on-’开始的,

    因此点击click的事件处理程序是onclick

    2. DOM0事件绑定

    DOM分为级别,DOM的标准分0级、1级、2级、3级,不同的标准,标准一直在升级。

    DOM1级没有定义相关的内容,

    DOM3级只是在DOM2级基础上增加了更多的时间类型,

    所以我们学习的重点还是DOM0级和DOM2的事件绑定

    接下来先了解DOM标准中的0级的事件绑定方法:

    2.1 DOM0 级事件绑定的用法

    语法:

    dom.on+type = fn;

    1. dom: 绑定事件的对象

    2. type: 为事件的类型

    3. fn : 为事件触发时执行的函数

      // 得到这个box
      var oDiv = document.getElementById("box");

      //事件
      oDiv.onclick = function(){
      alert("你好,点我干嘛,我烦着呢!!");
      }

    也可以绑定一个有名的函数,有名函数方便复用。当做事件处理程序

    oDiv.onclick = fun; //绑定的是函数,而不是函数的执行,所以不加圆括号。
    
    function fun(){
        alert("你好,点我干嘛,我烦着呢!!");
    }
    

    原来我们想要一个函数执行,必须调用这个函数,比如fun();

    但是现在你知道了,一个函数可以当做一个事件的处理函数,当这个事件发生的时候,函数也能执行了。

    2.2 DOM0级绑定事件处理函数的次数

    注意:一个dom对象同一个事件类型只能绑定一个事件处理函数

    // 得到这个box
    var oDiv = document.getElementById("box");
    
    // 第一次绑定点击事件事件
    oDiv.onclick = function(){
        alert("第一次绑定点击事件事件");
    }
    //第二次绑定点击事件
    oDiv.onclick = function(){
        alert("第二次绑定点击事件事件!");
    }
    

    我们会发现弹出的是“第二次绑定点击事件”,后面的会把前面的覆盖,就好像给一个对象的属性付了两次值,发生覆盖

    双击执行的事件

     <div id="box">双击
      </div>
      <script>
        box.ondblclick = function () {
          console.log("双击执行");
        }
      </script>
    
    2.3 DOM0级解除事件绑定

    语法:

    dom.on+type = null

    通过给元素的事件属性上绑定空对象null 来达到解除事件绑定

    oDiv.onclick = null;
    
    实现用户只能点击一次

    方法一通过判断拦截,缺点事件一直占用着内存,没有被销毁

      <div id="box">执行一次
      </div>
      <script>    
        var istrue = false;
        box.onclick = function () {
        if(istrue){
           return
        }
          istrue = true;
          console.log("只执行一次");
        }    
      </script>
    

    方法二事件不用了,可以考虑注销,释放内存

    <div id="box">执行一次
    </div>
    <script>  
        box.onclick = function () {
          console.log("只执行一次");
          box.onclick = null//this.onclick也可以
        }
    </script>
    

    3.批量绑定事件和事件排他

    3.1 批量绑定事件

    1. 利用for循环批量绑定事件。
           <style>
               #ulist li {
                 float: left;
                 list-style-type: none;
                 width: 100px;
                 height: 100px;
                 background-color: pink;
                 margin-right: 10px;
               }
             </style>
           </head>
           <body>
             <div>
               <ul id=ulist>
                 <li>1</li>
                 <li>2</li>
                 <li>3</li>
                 <li>4</li>
                 <li>5</li>
                 <li>6</li>
               </ul>
             </div>
             <script>
               //批量绑定事件
               var ali = document.querySelectorAll("#ulist li");
               var len = ali.length;
               for (var i = 0; i < len; i++) {   //for循环包裹添加绑定事件的语句。
                 ali[i].onclick = function () {
                   console.log("批量绑定事件");
                 }
               }
             </script>
    
    
    2、批量绑定事件,对序号的影响

    批量绑定事件获取索引的问题,for是同步语句,为每个li绑定事件,i最后为6。用户点击时触发相应的li里的函数,函数AO作用域中没有i,到GO中找,所以i为6

    方法一添加对象属性保存索引值

          <style>
            #ulist li {
              float: left;
              list-style-type: none;
              width: 100px;
              height: 100px;
              background-color: pink;
              margin-right: 10px;
            }
          </style>
        </head>
        
        <body>
          <div>
            <ul id=ulist>
              <li>0</li>
              <li>1</li>
              <li>2</li>
              <li>3</li>
              <li>4</li>
              <li>5</li>
            </ul>
          </div>
          <script>
            //li调用的onclick,所以每个函数的this就是ali[i],所以给ali[i]添加一个属性aLi[i].index =i
            var aLi = document.querySelectorAll("#ulist li");
            var len = aLi.length;
            for (var i = 0; i < len; i++) {
              aLi[i].index = i;  //任何一个对象,我们都可以通过点语法来设置新的属性。
              aLi[i].onclick = function () {
                console.log("批量绑定事件,我是" + this.index + "号");
              }
            }
          </script>
    

    方法二利用闭包,在for循环内部套一层自执行函数 IIFE(该函数有自己的作用域)

        <div>
            <ul id=ulist>
              <li>0</li>
              <li>1</li>
              <li>2</li>
              <li>3</li>
              <li>4</li>
              <li>5</li>
            </ul>
          </div>
          <script>
           
            var aLi = document.querySelectorAll("#ulist li");
            var len = aLi.length;
            for (var i = 0; i < len; i++) {
              (function (j) {//用j接受i传进来的值
                aLi[j].onclick = function () {
                  console.log("批量绑定事件,我是" + j + "号");
                }
              })(i)
            }
          </script>
    

    方法二的优化,j能用i代替,变量查询规则会沿着作用域链找

          <div>
            <ul id=ulist>
              <li>0</li>
              <li>1</li>
              <li>2</li>
              <li>3</li>
              <li>4</li>
              <li>5</li>
            </ul>
          </div>
          <script>
            var aLi = document.querySelectorAll("#ulist li");
            var len = aLi.length;
            for (var i = 0; i < len; i++) {
              (function (i) {//用j接受i传进来的值
                aLi[i].onclick = function () {
                  console.log("批量绑定事件,我是" + i + "号");
                }
              })(i)
            }
          </script>
    
    3.2 对应和排他

    排他

    方法一添加for循环所有变成pink,然后自己变成blue

        <head>
          <style>
            div#box>div {
              display: inline-block;
              list-style-type: none;
              width: 100px;
              height: 100px;
              background-color: pink;
              margin-left: 20px;
            }
          </style>
        </head>
        <body>
        <div id="box">
          <div>0</div>
          <div>1</div>
          <div>2</div>
          <div>3</div>
          <div>4</div>
          <div>5</div> 
        </div>
          <script>    
            var adiv = document.querySelectorAll('div#box>div');
            var alen = adiv.length;
            for(var i=0;i<alen;i++){
              adiv[i].index=i;
              adiv[i].onclick =function(){
                console.log(this.index);
                for(var j=0 ;j<alen;j++){//点击之前将所有的恢复成粉色
                  adiv[j].style.backgroundColor ="pink";
                }
                this.style.backgroundColor="blue";  //this就是点击的DOM元素
              }
            }
    

    方法二将每次索引保存起来

        <head>
          <style>
            div#box>div {
              display: inline-block;
              list-style-type: none;
              width: 100px;
              height: 100px;
              background-color: pink;
              margin-left: 20px;
            }
          </style>
        </head>
        <body>
          <div id="box">
            <div>0</div>
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div>5</div>
          </div>
          <script>
            var adiv = document.querySelectorAll('div#box>div');
            var index = 0;   // 保存索引
            var alen = adiv.length;
            for (var i = 0; i < alen; i++) {
              adiv[i].index = i;
              adiv[i].onclick = function () {
                adiv[index].style.backgroundColor = "pink";  //精准定位到上一个div索引,恢复成pink,轮播会用到。性能比for循环好,能不用for就不用
                this.style.backgroundColor = "blue";
                index = this.index;   //上一个点中的索引赋值给index
              }
            }
          </script>
    

    对应:点击第一排的p,第二排对应的p变红:

        aBox[this.idx].style.backgroundColor = “red”;
    
          <style>
            #box{
              margin-bottom: 15px;
            }
            div#box>div,
            div#wrap>div{
              display: inline-block;
              list-style-type: none;
              width: 100px;
              height: 100px;
              background-color: pink;
              margin-left: 20px;
            }
          </style>
        </head>
        <body>
          <div id="box">
            <div>0</div>
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div>5</div>
          </div>
          <div id="wrap">
            <div>0</div>
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div>5</div>
          </div>
          <script>
            var abox = document.querySelectorAll('div#box>div');
            var awrap = document.querySelectorAll("div#wrap>div");
        
            var index = 0;   // 保存索引
            var alen = abox.length;
            for (var i = 0; i < alen; i++) {
              abox[i].index = i;
              abox[i].onclick = function () {
                awrap[index].style.backgroundColor = "pink";  //精准定位到上一个div索引,恢复成pink,轮播会用到。性能比for循环好,能不用for就不用
                abox[index].style.backgroundColor="pink"//自己也排他
                awrap[this.index].style.backgroundColor = "blue";
                this.style.backgroundColor = "blue";//自己也变蓝色
        
                console.log(this.index);
                index = this.index;   //上一个点中的索引赋值给index
              }
            }
          </script>
    

    4. DOM2级事件监听

    DOM2级做了新的规范,不用on***来绑定监听了,而是使用一个方法

    4.1 主流浏览器事件的绑定和解绑方法
    1. 绑定事件方法
      // 绑定事件的方法
      addEventListener();

      add添加,Event事件,Listener监听
      它接受三个参数:什么事件、函数、是否监听捕获阶段。
      oBox.addEventListener("click",function(){},false);

      第1个参数:事件名不用写on, click、mouseover 、mouseout
      第2个参数:函数可以是匿名函数,也可以是有名函数
      第3个参数:布尔值(默认false,可以省略),true表示监听捕获、false表示监听冒泡阶段

    示例:

      <div id="box">
      DOM二级事件
      </div>
      <script>
        function haha(){
          console.log("DOM2");
          return function(){
            console.log(111);
          }
        }
        box.addEventListener('click',haha())//这里的haha是个自执行函数,返回的函数才是事件执行的函数
      </script>
    
    
    
    oBox.addEventListener("click", function(){
        alert("box1被点击,捕获阶段");
    }, false)
    

    第三个参数是true,表示监听box1的捕获阶段的单击事件。

    1. 事件绑定的this指向
      oBox.addEventListener('click',function(){
      console.log(this);
      },false)

      发现this指向oBox元素自身

    2. 可以绑定多个事件处理程序
      addEventListener可以重复添加相同事件名的事件:
      oBox.addEventListener("click", function(){
      alert("嘻嘻");
      }, false);

      oBox.addEventListener("click", function(){
          alert("哈哈");
      }, false);
      

      我们给box1的绑定了两个事件监听,不会覆盖,两个监听的函数都会执行,按照代码执行顺序。

      以下写法不是多个,而是同一个事件处理程序

      oBox.addEventListener("click", fn, false);
      
      oBox.addEventListener("click",fn, false);
      
      function fn(){
          alert("哈哈");
      }
      
    1. 解绑事件
      使用方法removeEventListener
      oBox.addEventListener("click", fn, false);
      // 解绑有名函数
      oBox.removeEventListener("click",fn, false);
      function fn(){
      alert("哈哈");
      }

      // 解绑匿名函数
      oBox.addEventListener("click",function(){
          console.log(11);
          oBox.removeEventListener("click",arguments.callee, false);
      }, false);
      
    4.2. 低版本IE的事件的绑定和解绑方法

    IE永远是个奇葩,

    IE 6、7、8不支持addEventListener()方法,

    1. IE 8及以下的事件绑定
      需要加on
      oBox.attachEvent("onclick",函数)

      没有第三个参数,也就是说,不能选择监听捕获、冒泡。只能监听冒泡。
      box1.attachEvent("onclick", function(){
      alert("box1");
      });

    第一个参数,必须写on,和addEventListener()不一样;

    第二个参数,就是事件处理函数

    没有第三个参数,只能监听冒泡。所以和on***写法一样。

    1. 低版本IE的事件监听方法的this指向
      oBox.attachEvent("onclick", function(){
      console.log(this === window); //true
      });

      低版本IE的事件监听attachEvent:**事件处理函数里面的this,不是触发事件的这个元素,而是window

    2. 可以绑定多个事件处理程序
      同一个事件名的多个监听,会反着执行:
      oBox.attachEvent("onclick", function(){
      alert(1);
      });

      oBox.attachEvent("onclick", function(){
          alert(2);
      });
      
      oBox.attachEvent("onclick", function(){
          alert(3);
      });
      // 弹出3、2、1。
      
    3. 解绑事件
      使用方法removeEventListener
      var oBox = document.getElementById("box");

      //  绑定事件
      oBox.attachEvent("onclick", fn);
      
      // 解除事件绑定
      oBox.detachEvent('onclick' ,fn);
      
      function fn(){
          alert("嘻嘻");
      }
      
    4.3 封装兼容方法
    1. DOM2级事件监听兼容
      <div id="box">
      DOM二级事件
      </div>
      <script>
       function addEvent(obj,type,callback){
           if(obj.addEventListener){ //主流浏览器,得到函数
               obj.addEventListener(type,callback,false);   //主流就执行这个函数,传参
           }else if(obj.attachEvent){  //谷歌是undefined IE低版本中是函数
               obj.attachEvent("on" + type,function(){  //IE绑定事件要加on,所以拼接
                   callback.call(obj);
               });
           }else{  //只支持DOM0级绑定事件
               obj["on" + type] = callback;
           }
       }
       addEvent(box,'click',function(){
         console.log(111);
       })
      </script>
    

    上面我们学习的就是一些理论知识,总结一下:

    4.4 DOM2级事件的绑定和解绑罗列
    1. 事件监听的兼容问题
      1.IE8以上主流浏览器
      dom.addEventListener(type,fn,false)
      this指向dom本身

      1. IE8及以下
        dom.attachEvent(‘on‘+type,fn)
        this指向window
    2. 解绑事件处理函数

    3. IE8以上主流浏览器
      dom.removeEventListener(type,fn,false)

    4. IE8及以下
      dom.detachEvent(‘on’+type,fn)

    5. 事件的分类

    5.1 鼠标事件

    onclick 点击鼠标左键触发

    oncontextmenu 点击鼠标右键触发(浏览器有默认的右键行为)不常用

    ondblclick 双击鼠标左键触发

    onmousedown 鼠标任意键按住时触发

    onmouseup 鼠标任意键抬起时触发

    onmouseenter` 鼠标进入元素时触发

    onmouseleave 鼠标离开元素时触发

    onmouseover 鼠标进去元素时触发

    onmouseout 鼠标离开元素时触发

    onmousemove 鼠标在元素上移动触发 ===>持续触发

    注意:

    onclick = onmousedown + onmouseup

           <style>
            .box{
            width: 100px;
            height: 100px;
            background-color: red;
            }
          </style>
        </head>
        <body>
          <div class="box">
           我是盒子
            </div>
            <script>
            var obox =document.querySelector(".box") 
            obox.onmouseenter=function(){
            console.log("onmouseenter");
            obox.style.height="200px";
            obox.style.backgroundColor="pink"
           }
           console.log(getComputedStyle(obox).backgroundColor);//获取元素样式属性
           console.log(window.innerWidth);//获取窗口尺寸
          </script>
    
    5.2 滚轮事件

    onmousewheel 鼠标滚轮在元素上滚动时触发(IE+chrome)

    DOMMouseScroll 鼠标滚轮在元素上滚动时触发(firefox)

    5.3 键盘事件

    onkeydown 按住键盘上任意键触发 ==>持续触发

    onkeypress 按住键盘上部分键触发 ==>持续触发

    onkeyup 键盘上按键抬起时触发

    5.4 资源事件

    onload 页面或者图片加载完成时触发

    5.5 window事件

    onresize 在窗口大小改变时触发

    onscroll 在页面滚动的时候触发

    5.6 焦点事件

    onfocus 得到焦点

    onblur 失去焦点

    相关文章

      网友评论

          本文标题:第十五节 JavaScript 事件及事件绑定

          本文链接:https://www.haomeiwen.com/subject/jubtxrtx.html