Vue3 Composition API事件监听器报错:无法操作undefined属性
Vue3 Composition API事件监听器报错解决
报错信息
第一个监听器报错:
Uncaught TypeError: Cannot set properties of undefined (setting 'width')
at HTMLDivElement.
第二个监听器报错:
Uncaught TypeError: Cannot read properties of undefined (reading 'contains')
at HTMLDivElement.
问题代码
<script setup> import { defineProps, ref, onMounted } from 'vue' import { useEventListener } from '@vueuse/core' const waveForm = ref(null) const hover = ref() const mainCover = ref(null) onMounted(() => { useEventListener(waveForm, 'pointermove', (evt) => { hover.style.width = `${evt.offsetX}px` }) useEventListener(mainCover, 'click', (e) => { if (mainCover.classList.contains("active")) { mainCover.classList.remove("active"); mainCover.classList.add("inactive"); } else { mainCover.classList.remove("inactive"); mainCover.classList.add("active"); } }) }) </script> <template> <div> <div ref="mainCover" id="main_cover"> </div> </div> <div ref="waveForm" id="waveform"> <div ref="hover" id="hover"></div> </div>> </template>
错误原因
- Vue3中通过
ref()创建的响应式引用,必须通过.value才能访问到绑定的真实DOM元素,直接使用变量名拿到的是Ref对象,而非DOM节点,自然没有style或classList属性。 hover变量初始化时未显式赋值,即便模板中绑定了ref,仍需通过.value获取DOM元素。
修复后的代码
<script setup> import { defineProps, ref, onMounted } from 'vue' import { useEventListener } from '@vueuse/core' const waveForm = ref(null) const hover = ref(null) // 显式初始化null,代码更规范 const mainCover = ref(null) onMounted(() => { useEventListener(waveForm, 'pointermove', (evt) => { // 通过.value访问真实DOM,增加非空判断避免意外报错 if (hover.value) { hover.value.style.width = `${evt.offsetX}px` } }) useEventListener(mainCover, 'click', (e) => { // 通过.value访问真实DOM,增加非空判断 if (mainCover.value) { const coverEl = mainCover.value if (coverEl.classList.contains("active")) { coverEl.classList.remove("active"); coverEl.classList.add("inactive"); } else { coverEl.classList.remove("inactive"); coverEl.classList.add("active"); } } }) }) </script> <template> <div> <div ref="mainCover" id="main_cover"> </div> </div> <div ref="waveForm" id="waveform"> <div ref="hover" id="hover"></div> </div> </template>
额外优化建议
- 用Vue的类绑定语法替代直接操作DOM类名,比如
:class="{active: isActive, inactive: !isActive}",更符合响应式开发思路,减少手动DOM操作。 - 始终给ref变量显式初始化
null,提升代码可读性。
内容的提问来源于stack exchange,提问作者AdRock
相关产品推荐
相关产品推荐

