浏览器原理 · 29/51
1. addEventListener 第三个参数 2. addEventListener 与 attachEvent 区别 3. 浏览器兼容性测试与内核 4. 浏览器兼容性问题 5. 浏览器内核与引擎 6. 浏览器图层创建条件 7. 浏览器多进程架构 8. 浏览器渲染机制 9. 浏览器存储方案 10. 浏览器版本检测方法 11. children 与 childNodes 区别 12. 常见浏览器兼容性问题 13. Chrome 页面进程数量 14. 坐标系统对比 15. 多标签页通讯方案 16. 删除 Cookie 17. 自定义事件 18. DOM 事件处理方式演进 19. 元素尺寸属性对比 20. DOM 节点操作 21. DOM 事件机制 22. addEventListener 与 attachEvent 的区别 23. 获取页面所有复选框 24. HTMLCollection 与 NodeList 区别 25. Hybrid 应用开发 26. 强缓存命中机制 27. 浏览器缓存机制 28. 页面编码与资源编码不一致处理 29. jQuery 事件绑定方法对比 30. Input 点击触发的事件顺序 31. JavaScript 浏览器兼容性问题 32. jQuery 多事件绑定实现 33. JSBridge 原理 34. 链接点击后 Hover 失效解决方案 35. 减少重绘和回流的性能优化 36. 移动端 300ms 点击延迟问题 37. 移动端视口配置 38. 移动端点击穿透问题解决 39. 移动端兼容性问题 40. JSBridge 原理与实现 41. 移动端 1px 像素问题解决方案 42. 浏览器渲染流程 43. 页面加载完成事件对比 44. Offset、Scroll、Client 属性对比 45. 同源策略与跨域解决方案 46. Script 标签位置对页面加载的影响 47. Service Worker 与 PWA 48. 存储方案对比:Cookie、Storage、IndexedDB 49. 强缓存默认时间 50. URL 到页面显示的完整过程 51. V8 引擎 JavaScript 执行过程

jQuery 事件绑定方法对比

bind、live、delegate、on 四种事件绑定方法的区别与用法

问题

jQuery 中的 bind()live()delegate()on() 有什么区别?

解答

这四个方法是 jQuery 事件绑定的演进历程,从 bind()on() 逐步优化。

bind()

直接绑定到元素上,不支持动态元素。

// 直接绑定到已存在的元素
$('.btn').bind('click', function() {
  console.log('clicked');
});

// 等价于
$('.btn').click(function() {
  console.log('clicked');
});

问题:动态添加的 .btn 元素不会有事件。

live()

通过事件冒泡到 document 实现委托,支持动态元素。

// 事件委托到 document
$('.btn').live('click', function() {
  console.log('clicked');
});

// 动态添加的 .btn 也能响应点击
$('body').append('<button class="btn">New Button</button>');

问题

  • 所有事件都冒泡到 document,性能差
  • jQuery 1.7 已废弃,1.9 移除

delegate()

指定委托的父元素,比 live() 更高效。

// 事件委托到指定父元素
$('#container').delegate('.btn', 'click', function() {
  console.log('clicked');
});

// 只在 #container 内的 .btn 生效

优点:可以控制事件冒泡的范围。

on()

jQuery 1.7+ 推荐方法,统一了前面所有方法。

// 直接绑定(替代 bind)
$('.btn').on('click', function() {
  console.log('clicked');
});

// 事件委托(替代 delegate)
$('#container').on('click', '.btn', function() {
  console.log('clicked');
  console.log($(this).text()); // this 指向触发事件的 .btn
});

// 绑定多个事件
$('.btn').on('click mouseenter', function(e) {
  console.log(e.type);
});

// 绑定多个事件到不同处理函数
$('.btn').on({
  click: function() {
    console.log('clicked');
  },
  mouseenter: function() {
    console.log('hovered');
  }
});

// 只执行一次
$('.btn').one('click', function() {
  console.log('只触发一次');
});

完整示例

<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
  <div id="container">
    <button class="btn">Button 1</button>
    <button class="btn">Button 2</button>
  </div>
  <button id="add">添加按钮</button>

  <script>
    // 事件委托:动态元素也能响应
    $('#container').on('click', '.btn', function() {
      alert($(this).text());
    });

    // 动态添加按钮
    $('#add').on('click', function() {
      $('#container').append('<button class="btn">New Button</button>');
    });
  </script>
</body>
</html>

方法对比表

方法委托位置动态元素状态
bind()元素自身已废弃
live()document已移除
delegate()指定父元素已废弃
on()可选推荐

关键点

  • on() 是目前唯一推荐的方法,其他都已废弃或移除
  • 事件委托的原理是利用事件冒泡,在父元素上监听子元素事件
  • 委托父元素越接近目标元素,性能越好
  • 动态添加的元素必须使用事件委托才能绑定事件
  • on() 的第二个参数(选择器)决定是直接绑定还是事件委托