面试题答案
一键面试事件解绑原理
在Vue组件销毁时,Vue会自动对组件自身绑定的DOM事件进行解绑。这是因为Vue内部维护了一个事件处理器的列表,当组件销毁时,它会遍历这个列表,调用对应的解绑函数(例如removeEventListener
),将事件处理器从对应的DOM元素上移除。
对于通过addEventListener
手动添加到DOM元素上的事件,Vue并不会自动解绑,需要手动处理。
需特别注意手动解绑事件的场景及举例
- 全局事件绑定:
- 场景:在组件内为
window
、document
等全局对象绑定事件。例如,监听window
的resize
事件来动态调整组件布局。 - 举例:
- 场景:在组件内为
<template>
<div>
<!-- 组件模板 -->
</div>
</template>
<script>
export default {
mounted() {
window.addEventListener('resize', this.handleResize);
},
methods: {
handleResize() {
// 处理窗口大小变化逻辑
}
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
}
}
</script>
如果不在beforeDestroy
钩子函数中手动解绑resize
事件,当组件销毁后,handleResize
函数依然会占用内存,导致内存泄漏。
- 第三方库的事件绑定:
- 场景:使用第三方库(如
Google Maps API
、D3.js
等)时,在组件内为其创建的对象绑定事件。例如,在使用Google Maps API
时,为地图上的某个标记绑定点击事件。 - 举例:假设使用
Google Maps API
:
- 场景:使用第三方库(如
<template>
<div id="map"></div>
</template>
<script>
export default {
mounted() {
const map = new window.google.maps.Map(this.$el, {
// 地图配置
});
const marker = new window.google.maps.Marker({
position: { lat: 0, lng: 0 },
map: map
});
marker.addListener('click', this.handleMarkerClick);
},
methods: {
handleMarkerClick() {
// 处理标记点击逻辑
}
},
beforeDestroy() {
const marker = // 获取到之前创建的标记
marker.removeListener('click', this.handleMarkerClick);
}
}
</script>
如果不手动解绑click
事件,当组件销毁后,点击事件处理器依然会存在,可能会引发未知问题并造成内存泄漏。
- 自定义DOM元素事件绑定:
- 场景:在组件内创建了自定义的DOM元素,并为其绑定了事件。例如,创建一个可拖拽的自定义元素。
- 举例:
<template>
<div id="draggable" ref="draggable"></div>
</template>
<script>
export default {
mounted() {
const draggable = this.$refs.draggable;
draggable.addEventListener('mousedown', this.handleDragStart);
},
methods: {
handleDragStart() {
// 处理拖拽开始逻辑
}
},
beforeDestroy() {
const draggable = this.$refs.draggable;
draggable.removeEventListener('mousedown', this.handleDragStart);
}
}
</script>
若不在组件销毁时手动解绑mousedown
事件,可能导致事件处理器在组件销毁后仍占用内存,引发内存泄漏。