🎧 useEventListener - 事件监听神器
🌟 介绍
想象一下,你的组件就像一个聪明的管家,能够在合适的时机自动监听各种事件,并在离开时优雅地清理干净。useEventListener 就是这样一个贴心的助手!
它会在组件 mounted 和 activated 时自动绑定事件,在 unmounted 和 deactivated 时自动解绑事件,让你告别手动管理事件监听器的烦恼。无论是窗口大小变化、鼠标点击,还是键盘按键,都能轻松搞定!
🚀 代码演示
基础用法 - 监听窗口事件
js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';
export default {
setup() {
// 🪟 监听窗口大小变化
useEventListener('resize', () => {
console.log('窗口大小改变了!');
});
// 📱 监听设备方向变化
useEventListener('orientationchange', () => {
console.log('设备方向改变了!');
});
// ⌨️ 监听键盘事件
useEventListener('keydown', (event) => {
if (event.key === 'Escape') {
console.log('用户按下了 ESC 键');
}
});
},
};指定目标元素 - 精准监听
js
import { ref, onMounted } from 'vue';
import { useEventListener } from '@vant/use';
export default {
setup() {
const buttonRef = ref();
const containerRef = ref();
onMounted(() => {
// 🎯 监听特定按钮的点击
useEventListener(
'click',
() => {
console.log('按钮被点击了!');
},
{ target: buttonRef }
);
// 📦 监听容器的滚动事件
useEventListener(
'scroll',
(event) => {
console.log('容器滚动位置:', event.target.scrollTop);
},
{ target: containerRef }
);
});
return {
buttonRef,
containerRef,
};
},
};手动清理 - 灵活控制
js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';
export default {
setup() {
const isListening = ref(true);
// 🧹 获取清理函数
const cleanup = useEventListener('resize', () => {
console.log('窗口大小改变');
});
// 🎛️ 动态控制监听状态
const toggleListener = () => {
if (isListening.value) {
cleanup(); // 停止监听
isListening.value = false;
} else {
// 重新开始监听
useEventListener('resize', () => {
console.log('重新开始监听窗口变化');
});
isListening.value = true;
}
};
return {
isListening,
toggleListener,
};
},
};高级配置 - 性能优化
js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';
export default {
setup() {
const scrollContainer = ref();
// 🚀 使用 passive 模式优化滚动性能
useEventListener(
'scroll',
(event) => {
// 不会调用 preventDefault,性能更好
console.log('滚动位置:', event.target.scrollTop);
},
{
target: scrollContainer,
passive: true, // 提升滚动性能
}
);
// 🎯 使用捕获模式
useEventListener(
'click',
(event) => {
console.log('在捕获阶段处理点击事件');
},
{
target: document.body,
capture: true, // 在捕获阶段触发
}
);
return {
scrollContainer,
};
},
};移动端适配 - 触摸事件
js
import { ref } from 'vue';
import { useEventListener } from '@vant/use';
export default {
setup() {
const touchArea = ref();
const startPos = ref({ x: 0, y: 0 });
// 👆 触摸开始
useEventListener(
'touchstart',
(event) => {
const touch = event.touches[0];
startPos.value = {
x: touch.clientX,
y: touch.clientY,
};
},
{ target: touchArea, passive: true }
);
// 👆 触摸移动
useEventListener(
'touchmove',
(event) => {
const touch = event.touches[0];
const deltaX = touch.clientX - startPos.value.x;
const deltaY = touch.clientY - startPos.value.y;
console.log('滑动距离:', { deltaX, deltaY });
},
{ target: touchArea, passive: true }
);
return {
touchArea,
};
},
};📚 API 参考
类型定义
ts
type Options = {
target?: EventTarget | Ref<EventTarget>;
capture?: boolean;
passive?: boolean;
};
function useEventListener(
type: string,
listener: EventListener,
options?: Options,
): () => void;参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 🎯 监听的事件类型(如 'click', 'resize', 'scroll') | string | - |
| listener | 🎧 事件回调函数 | EventListener | - |
| options | ⚙️ 可选的配置项 | Options | - |
Options 配置
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| target | 🎯 绑定事件的目标元素 | EventTarget | Ref<EventTarget> | window |
| capture | 📥 是否在事件捕获阶段触发 | boolean | false |
| passive | 🚀 设置为 true 时,表示 listener 永远不会调用 preventDefault,可提升性能 | boolean | false |
返回值
| 类型 | 说明 |
|---|---|
| () => void | 🧹 清理函数,调用后会移除事件监听器 |
🎯 实际应用场景
📱 移动端手势识别
js
// 实现左右滑动切换
const useSwipeGesture = (onSwipeLeft, onSwipeRight) => {
let startX = 0;
useEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
}, { passive: true });
useEventListener('touchend', (e) => {
const endX = e.changedTouches[0].clientX;
const diff = startX - endX;
if (Math.abs(diff) > 50) {
diff > 0 ? onSwipeLeft() : onSwipeRight();
}
}, { passive: true });
};🖥️ 响应式布局监听
js
// 监听屏幕尺寸变化,动态调整布局
const useResponsiveLayout = () => {
const isMobile = ref(window.innerWidth < 768);
useEventListener('resize', () => {
isMobile.value = window.innerWidth < 768;
});
return { isMobile };
};⌨️ 快捷键系统
js
// 实现全局快捷键
const useHotkeys = () => {
useEventListener('keydown', (e) => {
if (e.ctrlKey && e.key === 's') {
e.preventDefault();
console.log('保存快捷键触发');
}
});
};💡 最佳实践
✅ 推荐做法
js
// 1. 使用 passive 优化滚动性能
useEventListener('scroll', handler, { passive: true });
// 2. 监听特定元素而非全局
useEventListener('click', handler, { target: buttonRef });
// 3. 在需要时手动清理
const cleanup = useEventListener('resize', handler);
// 在某个条件下清理
if (shouldCleanup) cleanup();❌ 避免的用法
js
// ❌ 不要在事件处理器中执行耗时操作
useEventListener('scroll', () => {
// 避免复杂计算
heavyComputation();
});
// ❌ 不要忘记清理定时器等副作用
useEventListener('click', () => {
setInterval(() => {
// 可能导致内存泄漏
}, 1000);
});🛠️ 调试技巧
事件监听状态检查
js
// 添加调试信息
const cleanup = useEventListener('click', (e) => {
console.log('事件触发:', {
type: e.type,
target: e.target,
timestamp: Date.now(),
});
});
// 检查是否正确清理
onUnmounted(() => {
console.log('组件卸载,检查事件监听器是否已清理');
});性能监控
js
// 监控事件频率
let eventCount = 0;
useEventListener('scroll', () => {
eventCount++;
if (eventCount % 100 === 0) {
console.log(`滚动事件已触发 ${eventCount} 次`);
}
}, { passive: true });📚 相关文档
🎯 事件处理相关
- useClickAway - 点击外部区域 - 检测点击外部区域
- useToggle - 布尔值切换 - 状态切换管理
- usePageVisibility - 页面可见性 - 页面可见性检测
📱 移动端相关
- useRect - 元素位置 - 获取元素位置信息
- useScrollParent - 滚动父元素 - 查找滚动容器
- useWindowSize - 窗口尺寸 - 窗口尺寸监听
🎨 UI 交互相关
- useRaf - 动画帧 - 动画帧管理
- useRelation - 组件关联 - 父子组件通信
🛠️ 开发工具
- Vant Use 介绍 - 组合式 API 工具集
- 主题定制 - 样式主题配置