章节索引 :

自定义事件

自定义事件主要会被用于框架、组件设计与实现中。

自定义的事件有许多的创建方式,但实际的业务场景中几乎不会被用到,网络上的文献记载其具体的使用场景也相对较少。

1. 使用 Event 构造函数

使用 Event 构造函数就可以创建一个自定义事件。

实例演示
预览 复制
复制成功!
<style>
  .btn { border: 1px solid #4caf50; padding: 8px 12px; min-width: 200px; color: #4caf50; background: white; outline: none; }
  .btn:active { background: #4caf50; color: white; }
</style>

<div>
  <button class="btn">点击我</button>
</div>

<script>
  var afterClick = new Event('afterclick');

  var btnEle = document.querySelector('.btn');

  btnEle.addEventListener('afterclick', function() {
    alert('我是点击事件执行完后做的事情');
  });

  btnEle.onclick = function() {
    alert('我被点击了');

    this.dispatchEvent(afterClick);
  };
</script>
运行案例 点击 "运行案例" 可查看在线运行效果

图片描述

使用 new Event 可以创建一个自定义事件,事件名就是构造函数的第一个参数 afterclick,表示点击事件完成后做的事情。

创建一个自定义事件后需要给 DOM 元素绑定这个事件,只有绑定后才能触发,使用 addEventListener 来绑定事件。

随后再给按钮绑定点击事件,在事件末尾,即事情做完后,使用 dispatchEvent 触发这个自定义事件。

自定义事件是需要手动触发的!

Event 构造函数还支持第二个参数,其接受一个对象,可以传递三个属性,都为布尔值:

  • bubbles 默认 false ,表示是否会冒泡
  • cancelable 默认 false , 表示事件是否可以被取消
  • composed 默认 composed, 表示事件是否会在 Shadow DOM 根节点之外触发。

2. 使用 CustomEvent 构造函数

上面使用 Event 构造函数的例子,将其替换成 CustomEvent 构造函数也是一样可以执行的。

实例演示
预览 复制
复制成功!
<style>
  .btn { border: 1px solid #4caf50; padding: 8px 12px; min-width: 200px; color: #4caf50; background: white; outline: none; }
  .btn:active { background: #4caf50; color: white; }
</style>

<div>
  <button class="btn">点击我</button>
</div>

<script>
  var afterClick = new CustomEvent('afterclick');

  var btnEle = document.querySelector('.btn');

  btnEle.addEventListener('afterclick', function() {
    alert('我是点击事件执行完后做的事情,我被改成了 CustomEvent');
  });

  btnEle.onclick = function() {
    alert('我被点击了');

    this.dispatchEvent(afterClick);
  };
</script>
运行案例 点击 "运行案例" 可查看在线运行效果

图片描述

两个例子效果是一样的。

其主要的区别在参数和工作环境上,CustomEvent 是可以在 WebWorker 中被使用的,而 Event 不行。

CustomEvent 可以在构造函数的第二个参数中传递 detail 属性,在事件触发时,事件对象中就会携带这个 detail 属性。

假设现在想完成一个键盘的点击事件,即键盘上某个键按下并弹起后做的事情。

实例演示
预览 复制
复制成功!
<style>
  input {width: 200px;padding: 8px;font-size: 16px;outline: none;border: 1px dashed #4caf50;}
  input:focus {border: 1px solid #4caf50;}
</style>

<div>
  <input type="text">
</div>

<script>
  var inputEle = document.querySelector('input');

  var onKeyClick = function(e) {
    console.log(e);
    alert('现在输入框内容是:' + e.detail.value + ',触发的键是:' + e.detail.keyCode);
  };

  inputEle.addEventListener('keyup', (e) => {
    console.log('键盘按键弹起了');

    var keyClick = new CustomEvent('keyclick', {
      detail: {
        value: e.target.value,
        keyCode: e.keyCode,
      },
    });

    inputEle.addEventListener('keyclick', onKeyClick);

    inputEle.dispatchEvent(keyClick);

    inputEle.removeEventListener('keyclick', onKeyClick);
  });
</script>
运行案例 点击 "运行案例" 可查看在线运行效果

图片描述

这里通过 keyup 事件,在事件处理器的最末尾增加了一个 keyclick 事件。这里并没有结合 keydown 来判断按键的落下和弹起,因为一个按键要弹起,必定得先落下,所以只需要监听 keyup

其实可以看出这段代码比较奇怪,真正的业务场景并不会这样写,会选择直接调用 onKeyClick 函数。

<style>
  input {width: 200px;padding: 8px;font-size: 16px;outline: none;border: 1px dashed #4caf50;}
  input:focus {border: 1px solid #4caf50;}
</style>

<div>
  <input type="text">
</div>

<script>
  var inputEle = document.querySelector('input');

  var onKeyClick = function(value, keyCode) {
    alert('现在输入框内容是:' + value + ',触发的键是:' + keyCode);
  };

  inputEle.addEventListener('keyup', (e) => {
    console.log('键盘按键弹起了');

    onKeyClick(e.target.value, e.keyCode);
  });
</script>

这段代码的执行结果和采用 CustomEvent 的效果是一样的。

这就是为什么自定义事件更常用于框架或者库,因为暴露事件有时候比单纯的提供回调配置项更好理解和解耦。

3. document.createEvent

使用 document.createEvent 也可以用来创建自定义事件,但其由于许多配套属性、方法都已经从标准中移除,MDN 也不再建议开发者使用,所以这里不再深入探讨,只做了解。

4. 小结

自定义事件不常用,主要被应用于框架级别的设计上,日常开发很少有使用场景,许多场景下还会让代码变得冗余复杂。

前置知识
什么是JavaScript 开发与学习环境准备 调试方案
基础
JavaScript 变量 JavaScript 数据类型 JavaScript if 语句 JavaScript for 语句 JavaScript 算数运算符 JavaScript 比较运算符 JavaScript 逻辑运算符 JavaScript 表达式 JavaScript 函数 JavaScript 对象 JavaScript 字符串 JavaScript 数字 JavaScript 数组 JavaScript switch 语句 JavaScript while 语句 JavaScript break与continue JavaScript with document.cookie
内置对象
JavaScript Function JavaScript Math JavaScript Date JavaScript RegExp JavaScript JSON
JavaScript 与 DOM
什么是DOM DOM和JavaScript的关系 获取和操作 DOM 节点 JavaScript DOM与事件 JavaScript DOM 事件绑定 JavaScript DOM 事件对象 JavaScript DOM 事件流 JavaScript DOM 事件优化 JavaScript DOM 自定义事件
表单处理
使用 JavaScript 校验表单
BOM
BOM window 对象 常用的 BOM 相关对象 BOM 常用属性和方法
AJAX
JavaScript AJAX
进阶知识
JavaScript 异常处理 JavaScript 三元运算符 JavaScript 逗号操作符 JavaScript void JavaScript typeof JavaScript delete JavaScript debugger JavaScript getter &setter JavaScript 原型 JavaScript new操作符和构造函数 JavaScript instanceof JavaScript this JavaScript 严格模式 JavaScript 作用域 JavaScript 闭包 JavaScript 变量提升 JavaScript 对象包装器
常用库
jQuery Lodash moment.js swiper
进阶指南
ECMAScript6 Node.js Babel CSS 预处理器 代码规范 TypeScript Web Components 小程序 Vue / React / Angular JavaScript 关键字
常见疑点与误区
分号问题 对象属性访问问题 this 使用问题 浮点数精度问题 独一无二的 NaN 避免全局污染 控制台观察对象问题 根据环境选择语言特性
扩展
相关资源