You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:53:24