JS事件高级

目录

注册事件(2种方式)

事件监听兼容性解决方案

删除事件(解绑事件)

删除事件兼容性解决方案

DOM事件流

事件对象

什么是事件对象?

事件对象的使用

事件对象的兼容性处理

事件对象的属性和方法

e.target 和 this 的区别

阻止默认行为

阻止冒泡

阻止事件冒泡的兼容性处理

事件委托

js事件中的代理:

事件委托的原理

事件委托的作用

常用鼠标事件

 案例:禁止文字选中和禁止右键菜单

鼠标事件对象

 获取鼠标在页面的坐标

跟随鼠标的小天使案例

常用的键盘事件

键盘事件对象

模拟京东按下S键,自动获取焦点

模拟京东查询快递单号


注册事件(2种方式)

给元素添加事件,称为注册事件和绑定事件

注册事件有两种方式:传统方式监听注册方式

<body>

  <button>传统方式</button>
  <button>监听注册方式</button>
  <button>IE9之前支持</button>
  <script>
    var btn = document.querySelectorAll('button');
    // 1、传统方式
    /**
     * 特点:注册事件的唯一性
     * 同一个元素同一个事件只能设置一个处理函数,最后的
     * 处理函数会覆盖前面的处理函数
    */
    btn[0].onclick = function () {
      alert('按下了1');
    }
    btn[0].onclick = function () {
      alert('按下了2');
    }
    // 2、监听注册方式
    /**
     * w3c推荐方式
     * IE9之前不支持此方法,可使用attachEvent()代替
     * 特点:同一个元素可以注册多个监听器,按注册顺序依次执行
     * 三个参数:
     * 参数一:事件类型 省略开头on
     * 参数二:要调用的函数
     * 参数三:可选参数
    */
    btn[1].addEventListener('click', function () {
      alert('按下了1')
    });
    btn[1].addEventListener('click', function () {
      alert('按下了2')
    });

    // 3、attachEvent() IE9之前支持
    /**
     * 事件类型开头要带on    
     */
    btn[2].attachEvent('onclick', function () {
      alert('按下了');
    })
  </script>
</body>

事件监听兼容性解决方案

 function addEventListener(element, eventName, fn) {
      // 判断浏览器是否支持addEventListener方法
      if (element.addEventListener) {
        // 监听注册方式
        element.addEventListener(eventName, fn); // 第三个参数默认为false
      } else if (element.attachEvent) {
        // IE9之前支持
        element.attachEvent('on' + eventName, fn);
      } else {
        // 传统方式
        element['on' + eventName] = fn;
      }
    }

删除事件(解绑事件)

传统方式:

(1)eventTarget.onclick = null;

监听注册方式:

(1)eventTarget.removeEventListener(事件类型,处理函数);

(2)eventTarget.detachEvent(事件类型,处理函数);

<body>

  <div>1</div>
  <div>2</div>
  <div>3</div>
  <script>
    var box = document.querySelectorAll('div');
    // 1、onclick = null;
    box[0].onclick = function () {
      console.log('0');
      // this.onclick = null;
      box[0].onclick = null;
    }
    // 2、removeEventListener()
    /**
     * 注意:
     * (1) 这种方式想要删除事件,参数二必须是外部调用的函数
     * (2) 函数不用加小括号
    */
    box[1].addEventListener('click', fn);

    function fn() {
      console.log('1');
      box[1].removeEventListener('click', fn);
    }

    // 3. detachEvent IE9之前支持
    box[2].attachEvent('onclick', fn1);

    function fn1() {
      alert(33);
      box[2].detachEvent('onclick', fn1);
    }
  </script>
</body>

删除事件兼容性解决方案

    function removeEventListener(element, eventName, fn) {
      // 判断浏览器是否支持removeEventListener方法
      if (element.removeEventListener) {
        // 监听注册方式
        element.removeEventListener(eventName, fn); // 第三个参数默认为false
      } else if (element.detachEvent) {
        // IE9之前支持
        element.detachEvent('on' + eventName, fn);
      } else {
        // 传统方式
        element['on' + eventName] = null;
      }
    }

DOM事件流

html中的标签都是相互嵌套的,我们可以将元素想象成一个盒子装一个盒子,document是最外面的大盒子。
当你单击一个div时,同时你也单击了div的父元素,甚至整个页面。

那么是先执行父元素的单击事件,还是先执行div的单击事件 ???

事件流描绘的是从页面中接受事件的顺序

事件发生时会在元素节点之间按照特定顺序传播,这个传播过程DOM事件流

比如:我们给页面一个按钮注册了点击事件,点击了按钮时,也就点击了body,点击了html,点击了document。

 DOM事件流会经历三个阶段:

1、捕获阶段

2、当前目标阶段

3、冒泡阶段

举个例子:往水里丢石头,石头往水中下沉的过程称为捕获。石头落到水地产生泡泡,往水面上浮的过程称为冒泡。

注意:

1、JS代码中只能执行捕获或者冒泡其中一个阶段。

2、onclick和attachEvent只能得到冒泡阶段。

3、addEventListener()第三个参数如果是true,表示在事件捕获阶段,如果是空或者false,表示在冒泡阶段。

4、实际开发更关注事件冒泡。

5、有些事件没有冒泡。比如:onblur、onfocus、onmouseenter、onmouseleave 

6、事件冒泡有时候会带来麻烦,有时候又可以巧妙做某些事情。

<body>
  <div id="container">
    <div id="box">

    </div>
  </div>
  <script>
    // 事件冒泡
    // onclick 和 attachEvent 在冒泡阶段触发
    var con = document.querySelector('#container');
    var box = document.getElementById('box')
    // 里面盒子绑定事件
    con.addEventListener('click', function () {
      alert('0');
    }, false);
    // 外面盒子绑定事件
    box.addEventListener('click', function () {
      alert('1');
    }, false)
    // document注册事件
    document.addEventListener('click', function () {
      alert('2');
    })
    // 事件会以由内而外触发
    // 执行顺序:.box -> .container -> body -> html -> element
  </script>
</body>
<body>
  <div id="container">
    <div id="box">

    </div>
  </div>
  <script>
    // 事件捕获
    // addEventListener第三个参数是true,那么在捕获阶段触发
    var con = document.querySelector('#container');
    var box = document.getElementById('box')
    // 里面盒子绑定事件 第三个参数为true
    con.addEventListener('click', function () {
      alert('0');
    }, true);
    // 外面盒子绑定事件 第三个参数为true
    box.addEventListener('click', function () {
      alert('1');
    }, true)
    // document注册事件 第三个参数为true
    document.addEventListener('click', function () {
      alert('2');
    }, true)
    // 事件会以从外到内触发
    // 执行顺序:element -> html -> body -> .container -> .box
    // 2 -> 0 -> 1
  </script>
</body>

事件对象

什么是事件对象?

事件发生后,跟事件有关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象。

比如:

1、谁绑定了这个事件。

2、鼠标触发事件,会得到鼠标的相关信息,如鼠标位置

3、键盘触发事件的话,会得到键盘的相关信息,如按了哪个键

事件对象的使用

事件触发发生时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。

所以,在事件处理函数中声明一个形参用来接收事件对象

    var box = document.getElementById('box');
    box.onclick = function (event) {
      // 这个event就是事件对象,还可以命名为 e 或 evt
      console.log(event);
    }

事件对象的兼容性处理

事件对象本身的获取存在兼容问题

1、标准浏览器中是浏览器给方法传递的参数,只需要定义形参e中就可以获取到

2、在IE6 ~ 8 中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中查找

解决办法: e = e || window.event;

<body>
  <div id="box">
  </div>
  <script>
    var box = document.getElementById('box');
    box.onclick = function (event) {
      event = event || window.event;
      console.log(event);
    }
  </script>
</body>

事件对象的属性和方法

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

e.target 和 this 的区别

  • this 是事件绑定的元素(绑定这个事件处理函数的元素) 。

  • e.target 是事件触发的元素。

常情况下terget 和 this是一致的,
但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),
    这时候this指向的是父元素,因为它是绑定事件的元素对象,
    而target指向的是子元素,因为他是触发事件的那个具体元素对象。

<body>
  <ul>
    <li>1</li>
    <li>2</li>
  </ul>
  <script>
    var ul = document.querySelector('ul');
    ul.onclick = function (event) {
      /**
       * 一般情况下是一致的,但是在冒泡情况下是如下这样
      */
      console.log(this); // 返回绑定事件的元素对象 ul
      console.log(event.target); // 返回触发事件的元素对象 li
    }
  </script>
</body>

阻止默认行为

html中有一些标签有默认行为,例如a标签点击后,默认会进行页面跳转。

<body>
  <a href="http://www.baidu.com">链接</a>
  <script>
    var a = document.querySelector('a');

    a.addEventListener('click', function (e) {
      e.preventDefault(); // 阻止默认事件
    })
    // 传统的注册方式
    a.onclick = function (e) {
      // 普通浏览器使用
      e.preventDefault();
      // IE678使用
      e.returnValue = false;
      // 利用返回false也可以阻止默认事件
      return false;
    }
  </script>
</body>

阻止冒泡

事件冒本身的特性,会带来坏处,也会带来好处.、

标准写法:利用事件对象里面的stopPropgation方法

e.stopPropgation( )

非标准写法:IE6 ~ 8 利用事件对象cancelBubble属性

e.cancelBubble = true;

<body>
  <div class="container">
    <div class="box">

    </div>
  </div>
  <script>
    var con = document.querySelector('.container');
    var box = document.querySelector('.box');

    // 给外面盒子注册事件
    con.addEventListener('click', function (e) {
      alert(0);
    }, false)

    // 给里面盒子注册事件
    box.addEventListener('click', function (e) {
      alert(1);
      // 标准阻止冒泡方法
      e.stopPropagation();

      // 非标准阻止传播IE 6 ~ 8
      window.event.cancelBubble = true;
    }, false)
  </script>
</body>

阻止事件冒泡的兼容性处理

// 判断存在事件对象而且有事件对象的stopPropagation方法
    if (e && e.stopPropagation) {
      e.stopPropagation();
    } else {
      window.event.cancelBubble = true;
    }

事件委托

事件冒泡本身的特性,会带来坏处,也会带来好处

什么是事件委托?

就是把事件委托给别人,代为处理

事件委托也称为事件代理,在jQuery里面称为事件委派。

说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。

生活中的代理:

班上有100个学生,快递员有100个快递,如果一个一个送花费的时间很长。同时每个同学排队领取的时候,花费的时间也长。

解决方案:

快递员把100个快递,委托给班主任,班主任把这些快递放在办公室,同学们下课自行领取即可。

优势:

快递员省事,委托给班主任就走了,同学们领取也方便。

js事件中的代理:

  <ul>
    <li>这是li</li>
    <li>这是li</li>
    <li>这是li</li>
    <li>这是li</li>
    <li>这是li</li>
  </ul>

点击每个li都会弹出对话框,以前需要给每个li注册事件,不方便,而且访问DOM的次数越多,就会延长整个页面的交互就绪时间。

事件委托的原理

给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。

事件委托的作用

只操作了一次DOM,提高了程序的性能。

动态新创建的子元素,也拥有事件。

<body>
  <ul>
    <li>这是li</li>
    <li>这是li</li>
    <li>这是li</li>
    <li>这是li</li>
    <li>这是li</li>
  </ul>
  <script>
    /**
     * 事件委托的原理:给父元素添加事件,利用事件冒泡影响每一个子节点
    */
    var ul = document.querySelector('ul');
    ul.onclick = function (e) {
      console.log(e.target); // 打印事件的触发元素
      e.target.className = 'bgc'; // 改变事件触发者的类名
    }
  </script>
</body>

常用鼠标事件

 案例:禁止文字选中和禁止右键菜单

1、禁止鼠标右键菜单

contextmenu主要控制应该何时显示上下文菜单,用于程序员取消默认的上下文菜单。

    btn.addEventListener('contextmenu', function (e) {
      e.stopPropagation();
    })

2、禁止鼠标选中(selectstart 开始选中)

    btn.addEventListener('selectstart', function (e) {
      e.stopPropagation();
    })
<body>
  <p>这是一段不愿意分享的文字</p>
  <script>
    /**
     * 可以实现不允许复制的效果
    */
    document.addEventListener('contextmenu', function (e) {
      // 禁止右键菜单
      e.preventDefault();
    })

    document.addEventListener('selectstart', function (e) {
      // 禁止鼠标选中
      e.preventDefault();
    })
  </script>
</body>

鼠标事件对象

event事件对象是事件相关的一系列信息的集合

现阶段主要是用鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent

 获取鼠标在页面的坐标

<body>
  <script>
    document.addEventListener('click', function (e) {
      // 返回相对于浏览器窗口可视区的坐标
      console.log(e.clientX);
      console.log(e.clientY);

      console.log('-------------------');
      // 返回相当于文档页面的坐标
      console.log(e.pageX);
      console.log(e.pageY);

      console.log('-------------------');
      // 返回相对于电脑屏幕的坐标
      console.log(e.screenX);
      console.log(e.screenY);
    })
  </script>
</body>

跟随鼠标的小天使案例

  <style>
    img {
      position: absolute;
    }
  </style>
<body>
  <img src="./angel.gif" alt="小天使">
  <script>
    /**
     * 核心思路:
     * 给图片添加绝对定位,document添加鼠标移动事件,鼠标的x坐标、Y坐标,当做天使的top值left值
    */

    var img = document.querySelector('img');
    document.addEventListener('mousemove', function (e) {
      // 返回相当于浏览器窗口可视区的坐标
      console.log(e.clientX);
      console.log(e.clientY);

      var x = e.clientX;
      var y = e.clientY;
      img.style.left = x - 40 + 'px';
      img.style.top = y - 34 + 'px';
    })
  </script>
</body>

常用的键盘事件

键盘事件触发条件
onkeyup某个按键被松开时触发
onkeydown某个按键被按下时触发
onkeypress某个按键被按下时触发,不识别功能键,比如:箭头、Ctrl、Shift
  <script>
    // onkeyup 键盘弹起触发
    document.addEventListener('keyup', function () {
      console.log('我弹起了');
    }, false)

    // onkeydown 键盘按下触发 识别功能键
    document.onkeydown = function () {
      console.log('我按下了');
    }

    // onkeypress 键盘按下触发 不识别功能键
    document.onkeypress = function () {
      console.log('press按下');
    }

    // 三个事件的执行顺序:onkeydown -> onkeypress -> onkeyup
  </script>

键盘事件对象

键盘事件对象属性说明
keyCode返回该键的ASCII值

注意:

(1)onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写。

(2)在我们实际开发中,我们更多的使用keydown 和 keyup。

(3)keypress 不识别功能键,但是keyCode 属性能区分大小写,返回不同的ASCII值。

  <script>
    // 键盘事件对象可以得到相应键位的ASCII值
    document.addEventListener('keyup', function (e) {
      // console.log(e.keyCode);
      if (e.keyCode === 65) {
        console.log('按下了a键');
      } else {
        console.log('没有按下a键');
      }
    })

    // onkeypress 区分大小写
    document.addEventListener('keypress', function (e) {
      console.log(e.keyCode);
    })
  </script>

模拟京东按下S键,自动获取焦点

<body>
  <input type="text">

  <script>
    /**
  * 当按下s键时,利用输入框的focus()来获取焦点
  */
    // 获取输入框
    var input = document.querySelector('input');
    // 文档添加键盘事件
    document.addEventListener('keyup', function (e) {
      // 判断是否按下s键
      if (e.keyCode === 83) {
        // 输入框获取焦点
        input.focus();
      }
    })
  </script>
</body>

模拟京东查询快递单号

  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }


    div:nth-last-child(2) {
      width: 200px;
      height: 30px;
      background-color: #f1f1f1;
      border-radius: 5px;
      position: relative;
    }

    input {
      margin-top: 5px;
      width: 200px;
      height: 25px;
    }
  </style>
<body>

  <input type="text">
  <div class="con"></div>
  <script>
    var con = document.querySelector('.con');
    var input = document.querySelector('input');
    // 键盘事件
    /**
     * 键盘按下判断文本框是否为空
     * 空则不显示提示框
     * 不空则显示提示框,且将文本框的内容赋值给提示框
    */
    document.addEventListener('keyup', function () {
      if (input.value.length == 0) {
        con.style.display = 'none';
      } else {
        con.style.display = 'block';
        con.innerHTML = input.value;
      }
    })

    // 失去焦点事件
    // 当失去焦点时,不显示提示框
    input.onblur = function () {
      con.style.display = 'none';
    }

    // 获取焦点事件
    // 获取焦点时,文本框有内容则显示提示框,否则不显示
    input.onfocus = function () {
      if (this.value != '') {
        con.style.display = 'block';
      } else {
        con.style.display = 'none';
      }
    }

  </script>
</body>

效果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值