zoukankan      html  css  js  c++  java
  • Javascript面向对象基础

    事件基础

    • 事件概述

      • JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。
      • 简单理解: 触发--- 响应机制
      • 网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个 事件,然后去执行某些操作。
    • 时间三要素

      • 事件源(谁):触发事件的元素
      • 事件类型(什么事件): 例如 click 点击事件
      • 事件处理程序(做啥):事件触发后要执行的代码(函数形式),事件处理函数
    <body>
        <button id="btn">唐伯虎</button>
        <script>
            // 点击一个按钮,弹出对话框
            // 1. 事件是有三部分组成  事件源  事件类型  事件处理程序   我们也称为事件三要素
            //(1) 事件源 事件被触发的对象   谁  按钮
            var btn = document.getElementById('btn');
            //(2) 事件类型  如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
            //(3) 事件处理程序  通过一个函数赋值的方式 完成
            btn.onclick = function() {
                alert('点秋香');
            }
        </script>
    </body>
    
    • 执行事件的步骤
      • 获取事件源
      • 注册事件(绑定事件)
      • 添加事件处理程序(采取函数赋值形式)
    <body>
        <div>123</div>
        <script>
            // 执行事件步骤
            // 点击div 控制台输出 我被选中了
            // 1. 获取事件源
            var div = document.querySelector('div');
            // 2.绑定事件 注册事件
            // div.onclick 
            // 3.添加事件处理程序 
            div.onclick = function() {
                console.log('我被选中了');
            }
        </script>
    </body>
    
    • 分析事件三要素
      • 下拉菜单三要素
      • 关闭广告三要素

    事件高级

    • 注册事件

      • 给元素添加事件,称为注册事件或者绑定事件
      • 注册事件有两种方式:传统方式和监听注册方式
    • 传统注册方式

      • 利用on开头的事件 onclick
      • <button onclick="alert('hello world')"></button>
      • btn.onclick = function(){}
      • 特点:注册事件的唯一性
      • 同一个元素一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面的注册处理函数
    • 监听注册方式

      • W3C标准 推荐方式
      • addEventListener() 它是一个方法
      • IE9 之前的 IE 不支持此方法,可使用attachEvent()代替
      • 特点:同一个元素同一个事件可以注册多个监听器
      • 按注册顺序依次执行
    • 事件监听

      • eventTarget.addEventListener(type, listener[, useCapture]) 将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。IE9以后支持
        • type 事件类型字符串,比如 click mouseover
        • listener 事件处理函数,事件发生时,会调用该监听函数
        • useCapture 布尔值,true 在事件捕获阶段调用事件处理函数,false(默认值) 在事件冒泡阶段调用事件处理函数
      • eventTarget.attacheEvent(eventNameWithOn, callback) 将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触发指定的事件时,指定的回调函数就会被执行。IE678支持
        • eventNameWithOn 事件类型字符串,比如 onclick onmouseover
        • callback 事件处理函数,当目标触发事件时回调函数被调用
      <button>传统注册事件</button>
      <button>方法监听注册事件</button>
      <button>ie9 attachEvent</button>
      <script>
          var btns = document.querySelectorAll('button');
          // 1. 传统方式注册事件
          btns[0].onclick = function() {
              alert('hi');
          }
          btns[0].onclick = function() {
                  alert('hao a u');
              }
        // 2. 事件侦听注册事件 addEventListener 
        // (1) 里面的事件类型是字符串 必定加引号 而且不带on
        // (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
          btns[1].addEventListener('click', function() {
              alert(22);
          })
          btns[1].addEventListener('click', function() {
                  alert(33);
          })
          // 3. attachEvent ie9以前的版本支持
          btns[2].attachEvent('onclick', function() {
              alert(11);
          })
      </script>
    
    • 删除事件(解绑事件)
      • 传统注册方式
        • eventTarget.onclick = null;
      • 方法监听注册方法
        • eventTarget.removeEventListener(type, listener[, useCapture]);
        • eventTarget.detachEvent(eventNameWithOn, callback);
        <div>删除事件(解绑事件)</div>
        <div>删除事件(解绑事件)</div>
        <div>删除事件(解绑事件)</div>
        <script>
            var divs = document.querySelectorAll('div');
            divs[0].onclick = function() {
                alert(11);
                // 1. 传统方式删除事件
                divs[0].onclick = null;
            }
            // 2. removeEventListener 删除事件
            divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
            function fn() {
                alert(22);
                divs[1].removeEventListener('click', fn);
            }
            // 3. detachEvent
            divs[2].attachEvent('onclick', fn1);
    
            function fn1() {
                alert(33);
                divs[2].detachEvent('onclick', fn1);
            }
        </script>
    
    • 删除事件兼容性解决方案
      var removeEventListener = function(element, evenName, fn){
        // 判断当前浏览器是否支持 removeEventListener 方法
        if(element.removeEventListener){
          element.removeEventListener(eventName, fn);
        }else if(element.detachEvent){
          element.detachEvent('on'+eventName, fn );
        }else{
          element('on'+eventName) = null;
        }
      }
    

    DOM事件流

    • 概念

      • 事件流描述的是从页面中接收事件的顺序
      • 事件发生时,会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
    • 事件冒泡

      • IE最早提出,事件开始时由具体的元素接受,然后逐级向上传播到DOM最顶层节的过程
        <div class="father">
            <div class="son">son盒子</div>
        </div>
        <script>
            // onclick 和 attachEvent(ie) 在冒泡阶段触发
            // 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 
            // son -> father ->body -> html -> document
            var son = document.querySelector('.son');
    		// 给son注册单击事件
            son.addEventListener('click', function() {
                alert('son');
            }, false);
    		// 给father注册单击事件
            var father = document.querySelector('.father');
            father.addEventListener('click', function() {
                alert('father');
            }, false);
    		// 给document注册单击事件,省略第3个参数
            document.addEventListener('click', function() {
                alert('document');
            })
        </script>
    
    • 事件捕获
      • 网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到具体的元素接受的过程
        <div class="father">
            <div class="son">son盒子</div>
        </div>
        <script>
            // 如果addEventListener() 第三个参数是 true 那么在捕获阶段触发
            // document -> html -> body -> father -> son
             var son = document.querySelector('.son');
    		// 给son注册单击事件,第3个参数为true
             son.addEventListener('click', function() {
                 alert('son');
             }, true);
             var father = document.querySelector('.father');
    		// 给father注册单击事件,第3个参数为true
             father.addEventListener('click', function() {
                 alert('father');
             }, true);
    		// 给document注册单击事件,第3个参数为true
            document.addEventListener('click', function() {
                alert('document');
            }, true)
        </script>
    
    • DOM 事件流会经历3个阶段

      • 捕获阶段
      • 当前目标阶段
      • 冒泡阶段
    • DOM事件流

      • 我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。
      • JS代码中只能执行捕获或者冒泡其中的一个阶段
      • onclickattachEvent 只能得到冒泡阶段
      • 实际开发中,事件捕获很少用到,更关注事件冒泡
      • 有些事件是没有冒泡的,比如onblur onfocus onmouseenter onmouseleave

    事件对象

    • 什么是事件对象

      • 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象。
        • 谁绑定了这个事件。
        • 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
        • 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
    • 事件对象的使用

      • 事件触发发生时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。
      • 所以,在事件处理函数中声明1个形参用来接收事件对象。
      eventTarget.onclick = function(event){
        // 这个event就是事件对象 我们还喜欢写成e或者ent
      }
    
      eventTarget.addEventListener('click', function(event){
        // 这个event就是事件对象 我们还喜欢写成e或者ent
      })
    
      eventTarget.addEventListener('click', fn);
      function fn(event){
        // 这个event就是事件对象 我们还喜欢写成e或者ent
      }
    
    • 事件对象的兼容性处理
      • 事件对象本身的获取存在兼容问题:
        • 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
        • 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
        • 解决方案:e = e || window.event
        <div>事件对象</div>
        <script>
            var div = document.querySelector('div');
            div.onclick = function(e) {
              // 事件对象
              e = e || window.event;
              console.log(e);
              // 返回鼠标点击事件对象
            }
        </script>
    
    • 事件对象的属性和方法

      • e.target 返回触发事件的对象 标准
      • e.srcElement 返回触发事件的对象 非标准 IE6~8使用
      • e.type 返回事件的类型 比如 click
      • e.canceBubble 该属性阻止冒泡 非标准 IE6~8 使用
      • e.returnValue 该属性阻止默认事件(默认行为) 非标准 IE6~8 使用 比如不让链接跳转
      • e.preventDefault() 该方法阻止默认事件(默认行为) 比如不让链接跳转
      • e.stopPropagation() 阻止冒泡 标准
    • e.targetthis 的区别

      • this 是事件绑定的元素(绑定这个事件处理函数的元素)
      • e.target 是事件触发的元素
        • 常情况下terget 和 this是一致的
        • 但是在事件冒泡时,父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行
        • 这时候this指向的是父元素,因为它是绑定事件的元素对象
        • 而target指向的是子元素,因为他是触发事件的那个具体元素对象
        <div>通常情况</div>
        <script>
            var div = document.querySelector('div');
            div.addEventListener('click', function(e) {
                // e.target 和 this指向的都是div
                console.log(e.target);
                console.log(this);
            });
        </script>
    
      <ul>
        <li>事件冒泡</li>
        <li>事件冒泡</li>
        <li>事件冒泡</li>
      </ul>
      <script>
          var ul = document.querySelector('ul');
          ul.addEventListener('click', function(e) {
                // 我们给ul 绑定了事件  那么this 就指向ul  
                console.log(this); // ul
                // e.target 触发了事件的对象 我们点击的是li e.target 指向的就是li
                console.log(e.target); // li
          });
      </script>
    

    阻止默认行为

    • 阻止默认行为
      • html中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转
      <a href="http://www.baidu.com">百度</a>
      <script>
          // 2. 阻止默认行为 让链接不跳转 
          var a = document.querySelector('a');
          a.addEventListener('click', function(e) {
                e.preventDefault(); //  dom 标准写法
          });
          // 3. 传统的注册方式
          a.onclick = function(e) {
              // 普通浏览器 e.preventDefault();  方法
              e.preventDefault();
              // 低版本浏览器 ie678  returnValue  属性
              e.returnValue = false;
              // 我们可以利用return false 也能阻止默认行为 没有兼容性问题
              return false;
          }
      </script>
    

    阻止事件冒泡

    • 阻止事件冒泡
      • 事件冒泡本身的特性,会带来的坏处,也会带来的好处。
      • e.stopPropagation() 标准写法
      • e.cancelBubble = true; 非标写法 IE6~8
        <div class="father">
            <div>父亲</div>
            <div class="son">son儿子</div>
        </div>
        <script>
            var son = document.querySelector('.son');
    		// 给son注册单击事件
            son.addEventListener('click', function(e) {
                console.log('son');
                e.stopPropagation(); // stop 停止  Propagation 传播
                window.event.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
            }, false);
    
            var father = document.querySelector('.father');
    		// 给father注册单击事件
            father.addEventListener('click', function() {
                console.log('father');
            }, false);
    		// 给document注册单击事件
            document.addEventListener('click', function() {
                console.log('document');
            })
        </script>
    
    • 阻止事件冒泡的兼容性处理
    var stopBubble = function(e){
      if(e && e.stopPropagation){
        e.stopPropagation();
      }else{
        window.event.cancelBubble = true;
      }
    }
    

    事件委托

    • 事件委托原理

      • 给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。
      • 事件冒泡本身的特性,会带来的坏处,也会带来的好处。
      • 事件委托也称为事件代理,在 jQuery 里面称为事件委派。
    • 事件委托的作用

      • 我们只操作了一次 DOM ,提高了程序的性能。
      • 动态新创建的子元素,也拥有事件。
        <ul>
            <li>事件委托</li>
            <li>事件委托</li>
            <li>事件委托</li>
            <li>事件委托</li>
            <li>事件委托</li>
            <li>事件委托</li>
        </ul>
        <script>
            // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
            var ul = document.querySelector('ul');
            ul.addEventListener('click', function(e) {
                // e.target 这个可以得到我们点击的对象
                e.target.style.backgroundColor = 'pink';
            })
        </script>
    

    鼠标事件

    • 常见的鼠标事件

      • 鼠标单击左键触发:onclick
      • 鼠标经过触发:onmouseover
      • 鼠标离开触发:onmouseout
      • 获得鼠标焦点触发:onfocus
      • 失去鼠标焦点触发:onblur
      • 鼠标移动触发:onmousemove
      • 鼠标弹起触发:onmouseup
      • 鼠标按下触发:onmousedown
    • 禁止鼠标右击菜单

      • contextmenu 鼠标右击属性
      • 主要控制应该何时显示上下文菜单
      • 主要用于程序员取消默认的上下文菜单
      document.addEventListener('contextmenu', function(event){
        event.preventDefault();
      })
    
    • 禁止鼠标选中
      • selectstart 鼠标开始选中
      document.addEventListener('selectstart', function(event){
        event.preventDefault();
      })
    
      <body>
          我是一段不愿意分享的文字
          <script>
              // 1. contextmenu 我们可以禁用右键菜单
              document.addEventListener('contextmenu', function(e) {
                      e.preventDefault();
              })
              // 2. 禁止选中文字 selectstart
              document.addEventListener('selectstart', function(e) {
                  e.preventDefault();
              })
          </script>
      </body>
    
    • 鼠标事件对象

      • event事件对象是事件相关的一系列信息的集合
      • 现阶段我们主要是用鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent
    • 鼠标事件对象属性

      • e.clientX 返回鼠标相对于浏览器窗口可视区的X坐标
      • e.clientY 返回鼠标相对于浏览器窗口可视区的Y坐标
      • e.pageX 返回鼠标相对于文档页面的X坐标 IE9+支持
      • e.pageY 返回鼠标相对于文档页面的Y坐标 IE9+支持
      • e.screenX 返回鼠标相对于电脑屏幕的X坐标
      • e.screenY 返回鼠标相对于电脑屏幕的Y坐标
    • 获取鼠标在页面的坐标

      // 鼠标事件对象 MouseEvent
      document.addEventListener('click', function(e) {
          // 1. client 鼠标在可视区的x和y坐标
          console.log(e.clientX);
          console.log(e.clientY);
          console.log('---------------------');
    
          // 2. page 鼠标在页面文档的x和y坐标
          console.log(e.pageX);
          console.log(e.pageY);
          console.log('---------------------');
    
          // 3. screen 鼠标在电脑屏幕的x和y坐标
          console.log(e.screenX);
          console.log(e.screenY);
      })
    
    • 鼠标跟随
    <body>
        <div style=" 40px; height: 40px; background-color: aqua; position: relative;" id="pic"></div>
        <script>
            var pic = document.querySelector('#pic');
            document.addEventListener('mousemove', function(e) {
            	// 1. mousemove只要我们鼠标移动1px 就会触发这个事件
            	// 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 
                // 把这个x和y坐标做为图片的top和left 值就可以移动图片
            	var x = e.pageX;
            	var y = e.pageY;
            	console.log('x坐标是' + x, 'y坐标是' + y);
            	//3 . 千万不要忘记给left 和top 添加px 单位
            	pic.style.left = x- 20+ 'px';
            	pic.style.top = y- 20+ 'px';
        	});
        </script>  
    </body> 
    

    常用的键盘事件

    • 键盘事件

      • onkeyup 某个键盘按键被松开时触发
      • onkeydown 某个键盘按键按下时触发
      • onkeypress 某个键盘按键被按下时触发 但它不识别功能键 如ctrl shift →
    • 键盘事件触发

      • 如果使用addEventListener不需要加on
      • onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头等
      • 三个事件的执行顺序是:keydown keypress keyup
        // 常用的键盘事件
        //1. keyup 按键弹起的时候触发 
        document.addEventListener('keyup', function() {
            console.log('我弹起了');
        })
    
        //3. keypress 按键按下的时候触发  不能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keypress', function() {
                console.log('我按下了press');
        })
        //2. keydown 按键按下的时候触发  能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keydown', function() {
                console.log('我按下了down');
        })
        // 4. 三个事件的执行顺序  keydown -- keypress -- keyup
    
    • 键盘事件对象

      • keyCode 键盘事件对象属性 返回该键的ASCII值
      • onkeydownonkeyup不区分字母大小写,onkeypress区分字母大小写
      • 在实际开发中,我们更多的使用keydownKeyup,它能识别所有的键(包括功能键)
      • keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值
    • 使用keyCode属性判断用户按下哪个键

        // 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
        document.addEventListener('keyup', function(e) {
            console.log('up:' + e.keyCode);
            // 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
            if (e.keyCode === 65) {
                alert('您按下的a键');
            } else {
                alert('您没有按下a键')
            }
        })
        document.addEventListener('keypress', function(e) {
            // console.log(e);
            console.log('press:' + e.keyCode);
        })
    
    • 模拟京东按键输入内容
        <input type="text">
        <script>
            // 获取输入框
            var search = document.querySelector('input');
    		// 给document注册keyup事件
            document.addEventListener('keyup', function(e) {
                // 判断keyCode的值
                if (e.keyCode === 83) {
                    // 触发输入框的获得焦点事件
                    search.focus();
                }
            })
        </script>
    
    • 模拟京东快递单号查询
        <div class="search">
            <div class="con">123</div>
            <input type="text" placeholder="请输入您的快递单号" class="jd">
        </div>
        <script>
            // 获取要操作的元素
            var con = document.querySelector('.con');
            var jd_input = document.querySelector('.jd');
    		// 给输入框注册keyup事件
            jd_input.addEventListener('keyup', function() {
    				// 判断输入框内容是否为空
                    if (this.value == '') {
                        // 为空,隐藏放大提示盒子
                        con.style.display = 'none';
                    } else {
                        // 不为空,显示放大提示盒子,设置盒子的内容
                        con.style.display = 'block';
                        con.innerText = this.value;
                    }
                })
            // 给输入框注册失去焦点事件,隐藏放大提示盒子
            jd_input.addEventListener('blur', function() {
                    con.style.display = 'none';
                })
            // 给输入框注册获得焦点事件
            jd_input.addEventListener('focus', function() {
                // 判断输入框内容是否为空
                if (this.value !== '') {
                    // 不为空则显示提示盒子
                    con.style.display = 'block';
                }
            })
        </script>
    
  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/13551793.html
Copyright © 2011-2022 走看看