简体   繁体   English

jQuery 点击,添加 class 但如果 class 已经存在,也删除

[英]jQuery on click, add class but also remove if the class is already present

I have a nav menu that needs to trigger with clicks rather than hovers.我有一个导航菜单,需要通过点击而不是悬停来触发。 When the links are clicked, an .open class would be added to the parent li .单击链接时,将向父li添加一个.open class 。 If that parent already has the .open class, then it would get removed.如果该父级已经拥有.open class,那么它将被删除。 It would also be removed if another link is clicked on.如果单击另一个链接,它也会被删除。 So far I can get the class added when clicked and removed when a sibling is clicked, but not removed when it's already .open .到目前为止,我可以在单击同级时添加 class 并在单击同级时将其删除,但在它已经.open时不会删除。

I tried adding a hasClass conditional, but that didn't work either.我尝试添加一个hasClass条件,但这也不起作用。 Seemed like it reruns the function every time it's clicked and therefore ignores the hasClass conditional.似乎每次单击它都会重新运行 function ,因此忽略 hasClass 条件。

Can anyone provide help?任何人都可以提供帮助吗? I tried toggleClass , but that didn't work.我尝试toggleClass ,但没有奏效。

 $('li a').on('click', function() { $('li a').parent().removeClass('open'); $(this).parent().addClass('open'); });
 ul { list-style: none; } li { display: inline-block; padding: 10px; }.open { background-color: yellow; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav> <ul> <li> <a href="#">Item 1</a> </li> <li> <a href="#">Item 1</a> </li> </ul> </nav>

To do what you require you can use toggleClass() on the parent li when the element is clicked.要执行您需要的操作,您可以在单击元素时在父li上使用toggleClass() To remove the class from all other li elements you can use removeClass() along with not() to exclude the current li .要从所有其他li元素中删除 class ,您可以使用removeClass()not()来排除当前li Try this:尝试这个:

 $('li a').on('click', function() { let $li = $(this).parent().toggleClass('open'); $('li').not($li).removeClass('open'); });
 ul { list-style: none; } li { display: inline-block; padding: 10px; }.open { background-color: yellow; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav> <ul> <li> <a href="#">Item 1</a> </li> <li> <a href="#">Item 1</a> </li> </ul> </nav>

You can use您可以使用

  1. jquery toggleClass() to toggle yellow highlight (.open css class) on click/unclicking the same link. jquery toggleClass() 在单击/取消单击同一链接时切换黄色突出显示(.open css 类)。
  2. jquery siblings() to remove.open class on all the other li items. jquery 兄弟姐妹()删除。在所有其他 li 项目上打开 class。

Below is the link for the demo下面是demo的链接

https://jsfiddle.net/so1u8hq6/ https://jsfiddle.net/so1u8hq6/

 $('li a').on('click', function() { $(this).parent().siblings().removeClass('open'); $(this).parent().toggleClass('open'); });
 ul { list-style: none; } li { display: inline-block; padding: 10px; }.open { background-color: yellow; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav> <ul> <li> <a href="#">Item 1</a> </li> <li> <a href="#">Item 2</a> </li> <li> <a href="#">Item 3</a> </li> </ul> </nav>

Late to the party, but, after seeing the provided answers and some of the CSS you use I had to urge with my suggestions:聚会迟到了,但是,在看到提供的答案和您使用的一些 CSS 之后,我不得不提出我的建议:

  • UX.用户体验。 Avoid styling LI tags in general, or at least set the desired display and move on.通常避免设置 LI 标签的样式,或者至少设置所需的display并继续。 Style directly the a tag (with the necessary paddings etc.).直接为a标签设置样式(使用必要的填充等)。 You'll not only get less CSS to take care of, but also a larger touch interaction area .您不仅会得到更少的 CSS 照顾,而且触摸交互区域更大 Makes no sense to style something yellow if it's not a UI part of something interactable.如果它不是可交互的 UI 部分,则将其设置为黄色是没有意义的。 Also in JS, you don't need to take care about the LI wrappers any more - but only about the actual A Elements.同样在 JS 中,您不再需要关心LI包装器,而只需关心实际A元素。
  • Don't use common selectors like $('li a') - those might target any LI→A elements in your app.不要使用$('li a')这样的常见选择器——它们可能会针对您应用中的任何LI→A 元素。 Instead be more specific and use a Class like ie: .tabs for the parent UL .而是更具体并使用 Class ,例如: .tabs for parent UL Both in CSS and JS.在 CSS 和 JS 中。
  • Try to use Event Delegation (in jQuey using the .on() method).尝试使用事件委托(在 jQuey 中使用.on()方法)。 Not only it will help you to catch the Event.delegateTarget parent UL where needed, but also the this (the clicked element), but mainly reference all the "group" of a elements enclosed in the common parent.它不仅可以帮助您在需要的地方捕获Event.delegateTargetUL ,还可以捕获this (单击的元素),但主要引用包含在公共父元素中a元素的所有“组” That way you can have as many .tabs in a single page as you like.这样,您可以在一个页面中拥有任意数量的.tabs And yes, thanks to Event delegation you can even add dynamically LI Elements - and your JS will still work as expected.是的,多亏了事件委托,您甚至可以动态添加 LI 元素——您的 JS 仍将按预期工作。
  • Since you're using <a href="#"> Anchor elements, instead of (more properly) <button type="button>" Elements, you need to also use Event.preventDefault() in order to prevent the browser its default behavior and that's to follow anchors (scroll the page, navigate, etc...)由于您使用的是<a href="#">锚元素,而不是(更正确的) <button type="button>"元素,因此您还需要使用Event.preventDefault()以防止浏览器默认行为,那就是跟随锚点(滚动页面,导航等......)
  • Use the selector "a.open" when you want to target and remove the "open" class.当您想要定位并移除"open" class 时,请使用选择器"a.open" By just using "a" (or in other answers on this page - "li" ) you're uselessly touching elements trying to remove a class that's not there in the first place.通过使用"a" (或在此页面上的其他答案中 - "li" ),您将无用地触摸元素,试图删除首先不存在的 class。

Finally, here's the CSS retouch and the proper jQuery needed for your task:最后,这是您的任务所需的 CSS 润饰和正确的 jQuery:

 $(".tabs").on("click", "a", function(ev) { ev.preventDefault(); $("a.open", ev.delegateTarget).not(this).removeClass("open"); $(this).toggleClass("open"); });
 .tabs { display: flex; list-style: none; padding: 0; } /* Style your Anchors, not the dummy LI wrappers */.tabs a { padding: 10px; }.tabs a.open { background-color: yellow; }
 <ul class="tabs"> <li><a href="#">Item 1</a></li> <li><a href="#">Item 2</a></li> <li><a href="#">Item 3</a></li> </ul> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

To explain the only complicated line:解释唯一复杂的行:

$(
  "a.open",             // Target just the ones (if any) of class "open"
  ev.delegateTarget     // inside the common ".tabs" ancestor
)
  .not(this)            // ... not the clicked element (since later we'll use .toggleClass on it)
  .removeClass("open"); // ... remove that class "open" 

the rest is pretty self explanatory. rest 很容易解释。

Further read:进一步阅读:

So you only want the yellow background to appear as a signifier of user interaction rather than for the background color to be displayed?所以你只希望黄色背景作为用户交互的标志而不是显示背景颜色? Have you tried using the mousedown/mouseup functions instead of .on('click', function(){...} ?您是否尝试过使用mousedown/mouseup函数而不是.on('click', function(){...}

I was able to simulate the click event where the color showcases via this method:我能够通过这种方法模拟颜色展示的点击事件:

 $('li a').mousedown(function() { $('li a').parent().removeClass('open'); $(this).parent().addClass('open'); }); $('li a').mouseup(function() { $('li a').parent().removeClass('open'); });
 ul { list-style: none; } li { display: inline-block; padding: 10px; }.open { background-color: yellow; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav> <ul> <li> <a href="#">Item 1</a> </li> <li> <a href="#">Item 1</a> </li> </ul> </nav>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM