[英]How to reapply eventlistener on a computed array of divs in Vue 3?
我想显示一个 div 数组,目的是在悬停 div 时在 div 本身和子元素上添加一个 class。
div 数组是计算 function 的结果。代码如下:
<article
v-for="(article, index) in filteredArticles"
:key="article.id"
ref="articleRefs"
:ref-key="index"
@mouseenter="handleClass(index, 'add')"
@mouseleave="handleClass(index, 'remove')"
>
<!-- Content -->
</article
const articleRefs = ref<HTMLDivElement[]>([])
const articleList = ref([] as Article[])
const filteredArticles = computed(() => {
return activeTag.value !== ''
? articleList.value.filter((a) => a.tags.some((t) => t.Tag_id.title === activeTag.value))
: articleList.value
})
watch(
filteredArticles.value,
() => articleRefs.value = []
)
const handleClass = (index: number, action: 'add'|'remove') => {
const hoveredArticle = articleRefs.value[index]
hoveredArticle.classList[action]('animate')
hoveredArticle.querySelector('h2')?.classList[action]('glitch')
}
当页面加载时,一切正常,只要我更改标签以显示未被过滤掉的文章,我的handleClass
方法就会工作/被调用。
但是,如果过滤掉的文章再次显示,悬停时不会发生任何事情。
我错过了什么?
先感谢您
如果您使用循环遍历文章的数组索引并尝试将 map 指向 refs 的索引,则会出现问题。 如果您查看vue 文档,您会发现项目的顺序不能保证与数据数组的顺序相同
需要注意的是,ref 数组不保证与源数组顺序相同。
这将导致问题,即当使用 for 循环的索引时,您的 refs 数组中可能有不同的索引。
这个想法是用一个新的SingleArticle
Vue 组件将您的数据逻辑与表示逻辑分开(命名可能会有所不同,具体取决于您的上下文,但建议至少有两个单词的组件名称。)。 如果你按如下方式构建它,Vue 框架将确保你的更新逻辑有效,你不需要关心它。
animated
querySelector
获取内容中的元素并对其应用 class。<!-- vue sfc template: -->
<article
ref="articleRef"
:class="{ animated: isHover }"
v-html="content"
@mouseenter="isHover = true"
@mouseleave="isHover = false"
/>
// vue sfc script (or script setup)
import { ref, defineComponent } from 'vue';
export default defineComponent({
name: 'SingleArticle',
props: {
// what ever is in your article props
// but I add some example props to showcase the idea
content: String,
// ...
},
setup(props) {
var articleRef = ref<HTMLElement>(null);
var isHover = ref<boolean>(false);
watch(isHover, (currIsHover) => {
const action = currIsHover ? 'add' : 'remove';
articleRef.value?.querySelector('h2')?.classList[action]('glitch');
});
return {
articleRef,
isHover,
}
}
});
v-for
使用新组件<!-- inside the vue sfc template -->
<single-article
v-for="(article, index) in filteredArticles"
:key="article.id"
:content="article.content"
/>
// the main component only contains the logic for the
// filtering and the hovering logic is completely done
// inside the new single article component.
export default defineComponent({
setup() {
const articleList = ref<Article[]>([]);
const filteredArticles = computed(() => {
if (!activeTag.value) return articleList.value;
return articleList.value.filter(
(a) => a.tags.some((t) => t.Tag_id.title === activeTag.value)
);
}
return {
filteredArticles,
};
}
})
我没有测试实现,这只是根据我的想法写下来的。
该解决方案会将过滤器逻辑与文章的呈现逻辑分开,这将为您提供两个干净的组件,它们易于测试且易于理解。 更新将开箱即用,因为 vue 会响应式地迎合它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.