跳转到内容

Vue.js程序化事件监听器

来自代码酷

模板:Note

Vue.js程序化事件监听器[编辑 | 编辑源代码]

程序化事件监听器是Vue.js中通过JavaScript代码(而非模板语法)动态管理组件事件监听的高级技术。它允许开发者更灵活地控制事件的生命周期,特别适合需要精确控制事件订阅/取消订阅时机的复杂场景。

核心概念[编辑 | 编辑源代码]

与传统模板监听的区别[编辑 | 编辑源代码]

传统的事件监听通常在模板中使用`v-on`指令(或`@`缩写):

<!-- 模板方式 -->
<button @click="handleClick">点击</button>

而程序化监听则通过JavaScript API实现:

// 程序化方式
mounted() {
  this.$el.addEventListener('click', this.handleClick)
}

关键优势[编辑 | 编辑源代码]

  • 动态控制:可以随时添加/移除监听器
  • 精确作用域:可监听任意DOM元素或组件实例
  • 生命周期管理:避免内存泄漏
  • 条件监听:根据业务逻辑动态调整

基础API[编辑 | 编辑源代码]

Vue 2.x 的 $on/$off[编辑 | 编辑源代码]

export default {
  methods: {
    logEvent(payload) {
      console.log('事件触发:', payload)
    }
  },
  mounted() {
    // 添加监听
    this.$on('custom-event', this.logEvent)
    
    // 触发事件
    this.$emit('custom-event', { data: 123 })
    
    // 移除监听
    this.$off('custom-event', this.logEvent)
  }
}

Vue 3.x 的 mitt/events[编辑 | 编辑源代码]

Vue 3移除了`$on`/`$off`,推荐使用外部库如`mitt`:

import mitt from 'mitt'

const emitter = mitt()

// 监听
emitter.on('event', (data) => {
  console.log(data)
})

// 触发
emitter.emit('event', { priority: 'high' })

// 取消
emitter.off('event')

生命周期管理[编辑 | 编辑源代码]

自动清理模式[编辑 | 编辑源代码]

使用`once`选项可确保单次触发后自动移除:

this.$once('hook:beforeDestroy', () => {
  console.log('组件即将销毁')
})

组合式API示例[编辑 | 编辑源代码]

Vue 3的组合式API中推荐使用`onUnmounted`:

import { onUnmounted } from 'vue'

setup() {
  const timer = setInterval(() => console.log('心跳'), 1000)
  
  onUnmounted(() => {
    clearInterval(timer)
  })
}

高级模式[编辑 | 编辑源代码]

事件总线模式[编辑 | 编辑源代码]

创建全局事件中心(Event Bus):

// eventBus.js
import Vue from 'vue'
export const EventBus = new Vue()

// 组件A
EventBus.$on('data-updated', updateHandler)

// 组件B
EventBus.$emit('data-updated', newData)

性能优化技巧[编辑 | 编辑源代码]

1. 使用`passive`选项改善滚动性能:

window.addEventListener('scroll', onScroll, { passive: true })

2. 防抖模式实现:

import { debounce } from 'lodash'

mounted() {
  this.debouncedResize = debounce(this.handleResize, 200)
  window.addEventListener('resize', this.debouncedResize)
}

实战案例[编辑 | 编辑源代码]

拖拽组件实现[编辑 | 编辑源代码]

export default {
  data() {
    return {
      isDragging: false
    }
  },
  methods: {
    startDrag(e) {
      this.isDragging = true
      document.addEventListener('mousemove', this.drag)
      document.addEventListener('mouseup', this.stopDrag)
    },
    drag(e) {
      if (this.isDragging) {
        this.$emit('dragging', { x: e.clientX, y: e.clientY })
      }
    },
    stopDrag() {
      this.isDragging = false
      document.removeEventListener('mousemove', this.drag)
      document.removeEventListener('mouseup', this.stopDrag)
    }
  }
}

键盘快捷键系统[编辑 | 编辑源代码]

const keyMap = {
  'ArrowUp': 'moveUp',
  'ArrowDown': 'moveDown'
}

mounted() {
  window.addEventListener('keydown', (e) => {
    const action = keyMap[e.key]
    if (action) {
      this.$emit('shortcut', action)
    }
  })
}

常见问题[编辑 | 编辑源代码]

内存泄漏预防[编辑 | 编辑源代码]

graph LR A[添加监听] --> B[忘记移除] B --> C[内存泄漏] D[正确做法] --> E[mounted添加] D --> F[beforeDestroy移除]

Vue 3迁移指南[编辑 | 编辑源代码]

| Vue 2 API | Vue 3替代方案 | |----------------|-----------------------| | `this.$on` | `mitt`/自定义事件总线 | | `this.$once` | `onMounted` + 手动移除 | | `this.$off` | `emitter.off` |

数学表达[编辑 | 编辑源代码]

事件触发频率计算可使用泊松过程模型: P(N(t)=n)=(λt)neλtn! 其中:

  • λ 为事件发生率
  • t 为时间间隔
  • n 为事件次数

页面模块:Message box/ambox.css没有内容。

总结[编辑 | 编辑源代码]

程序化事件监听为Vue应用提供了更精细的事件控制能力,特别适合:

  • 需要动态添加/移除监听器的场景
  • 与非Vue系统的DOM元素交互
  • 构建复杂的事件驱动型应用

通过合理使用这些API,可以构建出更健壮、更易维护的Vue.js应用程序。