javascript - 在 Vue 中悬停时向元素添加类,而不使用数据
问题描述
在 Vue 组件中,我有一个这样的菜单:
<ul class="menu-outer-wrapper">
<li><a href="/foo-1">Foo 1</a></li>
<li class="has-children">
<a href="/foo-2">Foo 2</a>
<ul>
<li><a href="/child-1">Child 1</a></li>
<li><a href="/child-2">Child 2</a></li>
<li><a href="/child-3">Child 3</a></li>
</ul>
</li>
<li><a href="/foo-5">Foo 5</a></li>
<li class="has-children">
<a href="/foo-6">Foo 6</a>
<ul>
<li><a href="/child-1">Child 1</a></li>
<li><a href="/child-2">Child 2</a></li>
</ul>
</li>
<li><a href="/foo-7">Foo 7</a></li>
<li><a href="/foo-8">Foo 8</a></li>
</ul>
我想在悬停时将类添加hovered
到li.has-children
-elements ( mouseenter
) (以便能够为该下拉列表的子项制作一些更好的动画。并在mouseleave
.
我知道有一些选项可以使用纯 CSS 来做到这一点,但是控制延迟和软淡入是一件痛苦的事情(并且很快就会变得非常混乱,无需添加一些类)。
我想象做这样的事情:
...
mounted(){
let liWithChildren = document.querySelectorAll( '.menu-outer-wrapper > li.has-children' );
liWithChildren.forEach( (event, window) => {
// Somehow add the class to the hovered element here.
// But I don't know how. Or if it's a good/bad idea (performance-wise).
}
}
但这是要走的路吗?我可以在不使用的情况下做到这一点吗data
(因为菜单是由 CMS 系统动态生成的。
更新 1
我试图让我的降价代码可读。所以我想避免这样的事情:
<ul class="menu-outer-wrapper">
<li :class="[ { 'hovered' : someVar } ]">
<a href="/foo-1">Foo 1</a>
</li>
<li :class="[ { 'hovered' : someVar }, 'has-children' ]">
<a href="/foo-2">Foo 2</a>
<ul>
<li><a href="/child-1">Child 1</a></li>
<li><a href="/child-2">Child 2</a></li>
<li><a href="/child-3">Child 3</a></li>
</ul>
</li>
<li :class="[ { 'hovered' : someVar } ]">
<a href="/foo-3">Foo 2</a>
</li>
...
...
...
两者都因为它不会与动态生成的菜单融为一体。而且因为它给降价添加了很多噪音。
更新 2
我简化了这个例子,使它更容易理解。但由于评论,我想我会详细说明动态生成的菜单。我正在做这样的事情:
<nav id="secondary-menu" v-if="secondaryMenu">
<ul>
<li
:class="[ { 'has-children': r.children } ]"
v-for="(r, r_key, r_index) in secondaryMenu">
<a :href="r.url" :title="r.title">
{{ r.title }}
</a>
<ul class="children" v-if="r.children">
<li v-for="(c1, c1_key, c1_index) in r.children">
<a :href="c1.url" :title="c1.title">
{{ c1.title }}
</a>
</li>
</ul>
</li>
</ul>
</nav>
解决方案
你只需要@mouseenter
and@mouseleave
事件。您需要做的就是在所有可能有子项的列表项上侦听适当的事件,然后如果目标元素具有“有子项”类,则执行您的类添加(或删除)。这是我的做法:
<template>
<nav id="secondary-menu" v-if="secondaryMenu">
<ul>
<li
:class="[{ 'has-children': r.children }]"
v-for="(r, r_key, r_index) in secondaryMenu"
:key="`${r_key}-${r_index}`"
@mouseenter="addClass"
@mouseleave="removeClass"
>
<a :href="r.url" :title="r.title">
{{ r.title }}
</a>
<ul class="children" v-if="r.children">
<li
v-for="(c1, c1_key, c1_index) in r.children"
:key="`${c1_key}-${c1_index}`"
>
<a :href="c1.url" :title="c1.title">
{{ c1.title }}
</a>
</li>
</ul>
</li>
</ul>
</nav>
</template>
<script>
export default {
name: "HoverNav",
props: {
secondaryMenu: {
type: Array,
required: true,
},
},
methods: {
addClass: function (e) {
if (e.target.classList.contains("has-children")) {
e.target.classList.add("hovered");
}
},
removeClass: function (e) {
if (e.target.classList.contains("has-children")) {
e.target.classList.remove("hovered");
}
},
},
};
</script>
这是一个非常不美观的沙箱。让我知道这是否适合你:)
https://codesandbox.io/s/headless-brook-ysq97?file=/src/components/HoverNav.vue:0-1169
推荐阅读
- php - 必须是数组类型,给定字符串
- node.js - s3.deleteObject 没有响应错误或成功
- node.js - 发送(节点快递)和接收数据(reactjs)
- bash - 如何重用`apt update`和`apt upgrade`命令的`apt up`部分在一行中按顺序执行
- routes - 如何在标记之间创建路线?
- android - 协程 - 函数与过程
- swift - 使用 GTMAppAuth 在 Swift 中调用 Google Sheets API
- google-cloud-spanner - 删除 1 行父表的 Spanner 突变限制
- java - 任何 List Java中的分页
- c# - SonarQube 扫描仪失败并出现“不在 git 工作树内”错误