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

Vue3中如何为计算属性返回的div数组重新绑定事件监听器?

问题原因及解决方案

核心问题

你遇到的问题源于三个关键错误:

  1. watch监听对象错误:你监听的是filteredArticles.value(普通数组)而非响应式的filteredArticles计算属性,导致过滤条件变化时articleRefs未被正确重置,新渲染的DOM元素会追加到旧的ref数组中,索引完全混乱。
  2. 依赖v-for的index匹配DOM:数组被过滤/重新排序后,v-for的index会重新计算,但ref数组的索引和实际渲染的DOM元素无法一一对应,hover时会取到错误的DOM元素。
  3. 不必要的DOM操作:用ref手动操作DOM不符合Vue的声明式设计思路,反而容易引发索引不匹配问题。

推荐解决方案:声明式类绑定(无需操作DOM)

利用Vue的响应式系统,完全避免索引和DOM匹配问题:

模板代码

<article
    v-for="article in filteredArticles"
    :key="article.id"
    @mouseenter="hoveredArticleId = article.id"
    @mouseleave="hoveredArticleId = null"
    :class="{ animate: hoveredArticleId === article.id }"
>
    <h2 :class="{ glitch: hoveredArticleId === article.id }">
        <!-- 标题内容 -->
    </h2>
    <!-- 其他内容 -->
</article>

脚本代码

const articleList = ref([] as Article[])
const activeTag = ref('')
// 跟踪当前hover的文章ID
const hoveredArticleId = ref<number | null>(null)

const filteredArticles = computed(() => {
    return activeTag.value !== ''
        ? articleList.value.filter(a => a.tags.some(t => t.Tag_id.title === activeTag.value))
        : articleList.value
})

修复原有代码的方案(若坚持DOM操作)

如果需要保留原有的DOM操作逻辑,需做以下修改:

  1. 修正watch监听对象,确保响应式触发
  2. 通过事件对象直接获取当前元素,不再依赖index

模板代码

<article
    v-for="article in filteredArticles"
    :key="article.id"
    @mouseenter="handleClass($event, 'add')"
    @mouseleave="handleClass($event, 'remove')"
>
    <!-- Content -->
</article>

脚本代码

const articleList = ref([] as Article[])
const activeTag = ref('')

const filteredArticles = computed(() => {
    return activeTag.value !== ''
        ? articleList.value.filter(a => a.tags.some(t => t.Tag_id.title === activeTag.value))
        : articleList.value
})

// 修正watch监听,监听响应式计算属性
watch(filteredArticles, () => {
    // 不再依赖ref数组,此处可省略清空逻辑
}, { immediate: true })

const handleClass = (event: MouseEvent, action: 'add'|'remove') => {
    // 通过事件对象获取当前触发hover的元素
    const hoveredArticle = event.currentTarget as HTMLDivElement
    hoveredArticle.classList[action]('animate')
    hoveredArticle.querySelector('h2')?.classList[action]('glitch')
}

内容的提问来源于stack exchange,提问作者Jaeger

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:45:30