Js 在单击时切换类

如何在 vue.js 中切换类?

我有以下条件:

<th class="initial " v-on="click: myFilter">
<span class="wkday">M</span>
</th>


new Vue({
el: '#my-container',
data: {},
methods: {
myFilter: function(){
// some code to filter users
}
}
});

当我点击 <th>标签时,我想将 active作为一个类应用,如下所示:

<th class="initial active" v-on="click: myFilter">
<span class="wkday">M</span>
</th>

这需要切换,也就是说,每次点击都需要添加/删除类。

356511 次浏览

You could have the active class be dependent upon a boolean data value:

<th
class="initial "
v-on="click: myFilter"
v-class="{active: isActive}">
<span class="wkday">M</span>
</th>


new Vue({
el: '#my-container',


data: {
isActive: false
},


methods: {
myFilter: function() {
this.isActive = !this.isActive;
// some code to filter users
}
}
})

This answer relevant for Vue.js version 2

<th
class="initial "
v-on:click="myFilter"
v-bind:class="{ active: isActive }"
>
<span class="wkday">M</span>
</th>

The rest of the answer by Douglas is still applicable (setting up the new Vue instance with isActive: false, etc).

Relevant docs: https://v2.vuejs.org/v2/guide/class-and-style.html#Object-Syntax and https://v2.vuejs.org/v2/guide/events.html#Method-Event-Handlers

In addition to NateW's answer, if you have hyphens in your css class name, you should wrap that class within (single) quotes:

<th
class="initial "
v-on:click="myFilter"
v-bind:class="{ 'is-active' : isActive}"
>
<span class="wkday">M</span>
</th>

See this topic for more on the subject.

Without the need of a method:

<!-- html element, will display'active' class if showMobile is true -->
<!-- clicking on the elment will toggle showMobileMenu to true and false alternatively -->
<div id="mobile-toggle"
:class="{ active: showMobileMenu }"
@click="showMobileMenu = !showMobileMenu">
</div>

vue.js app

data: {
showMobileMenu: false
}

I've got a solution that allows you to check for different values of a prop and thus different <th> elements will become active/inactive. Using vue 2 syntax.

<th
class="initial "
@click.stop.prevent="myFilter('M')"
:class="[(activeDay == 'M' ? 'active' : '')]">
<span class="wkday">M</span>
</th>
...
<th
class="initial "
@click.stop.prevent="myFilter('T')"
:class="[(activeDay == 'T' ? 'active' : '')]">
<span class="wkday">T</span>
</th>






new Vue({
el: '#my-container',


data: {
activeDay: 'M'
},


methods: {
myFilter: function(day){
this.activeDay = day;
// some code to filter users
}
}
})

If you need more than 1 class

You can do this:

<i id="icon"
v-bind:class="{ 'fa fa-star': showStar }"
v-on:click="showStar = !showStar"
>
</i>


data: {
showStar: true
}

Notice the single quotes ' around the classes!

Thanks to everyone else's solutions.

If you don't need to access the toggle from outside the element, this code works without a data variable:

<a @click="e => e.target.classList.toggle('active')"></a>

This example is using Lists: When clicking in some li it turn red

html:

<div id="app">
<ul>
<li @click="activate(li.id)" :class="{ active : active_el == li.id }" v-for="li in lista">\{\{li.texto}}</li>
</ul>
</div>

JS:

var app = new Vue({
el:"#app",
data:{
lista:[{"id":"1","texto":"line 1"},{"id":"2","texto":"line 2"},{"id":"3","texto":"line 3"},{"id":"4","texto":"line 4"},{"id":"5","texto":"line 5"}],
active_el:0
},
methods:{
activate:function(el){
this.active_el = el;
}
}
});

css

ul > li:hover {
cursor:pointer;
}
.active {
color:red;
font-weight:bold;
}

Fiddle:

https://jsfiddle.net/w37vLL68/158/

new Vue({
el: '#fsbar',
data:{
isActive: false
},
methods: {
toggle: function(){
this.isActive = !this.isActive;
}
}
});
/*
DEMO STYLE
*/
@import "https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700";




body {
font-family: 'Poppins', sans-serif;
background: #fafafa;
}


p {
font-family: 'Poppins', sans-serif;
font-size: 1.1em;
font-weight: 300;
line-height: 1.7em;
color: #999;
}


a, a:hover, a:focus {
color: inherit;
text-decoration: none;
transition: all 0.3s;
}


.navbar {
padding: 15px 10px;
background: #fff;
border: none;
border-radius: 0;
margin-bottom: 40px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
}


.navbar-btn {
box-shadow: none;
outline: none !important;
border: none;
}


.line {
width: 100%;
height: 1px;
border-bottom: 1px dashed #ddd;
margin: 40px 0;
}


i, span {
display: inline-block;
}


/* ---------------------------------------------------
SIDEBAR STYLE
----------------------------------------------------- */
.wrapper {
display: flex;
align-items: stretch;
}


#sidebar {
min-width: 250px;
max-width: 250px;
background: #7386D5;
color: #fff;
transition: all 0.3s;
}


#sidebar.active {
min-width: 80px;
max-width: 80px;
text-align: center;
}


#sidebar.active .sidebar-header h3, #sidebar.active .CTAs {
display: none;
}


#sidebar.active .sidebar-header strong {
display: block;
}


#sidebar ul li a {
text-align: left;
}


#sidebar.active ul li a {
padding: 20px 10px;
text-align: center;
font-size: 0.85em;
}


#sidebar.active ul li a i {
margin-right:  0;
display: block;
font-size: 1.8em;
margin-bottom: 5px;
}


#sidebar.active ul ul a {
padding: 10px !important;
}


#sidebar.active a[aria-expanded="false"]::before, #sidebar.active a[aria-expanded="true"]::before {
top: auto;
bottom: 5px;
right: 50%;
-webkit-transform: translateX(50%);
-ms-transform: translateX(50%);
transform: translateX(50%);
}


#sidebar .sidebar-header {
padding: 20px;
background: #6d7fcc;
}


#sidebar .sidebar-header strong {
display: none;
font-size: 1.8em;
}


#sidebar ul.components {
padding: 20px 0;
border-bottom: 1px solid #47748b;
}


#sidebar ul li a {
padding: 10px;
font-size: 1.1em;
display: block;
}
#sidebar ul li a:hover {
color: #7386D5;
background: #fff;
}
#sidebar ul li a i {
margin-right: 10px;
}


#sidebar ul li.active > a, a[aria-expanded="true"] {
color: #fff;
background: #6d7fcc;
}




a[data-toggle="collapse"] {
position: relative;
}


a[aria-expanded="false"]::before, a[aria-expanded="true"]::before {
content: '\e259';
display: block;
position: absolute;
right: 20px;
font-family: 'Glyphicons Halflings';
font-size: 0.6em;
}
a[aria-expanded="true"]::before {
content: '\e260';
}




ul ul a {
font-size: 0.9em !important;
padding-left: 30px !important;
background: #6d7fcc;
}


ul.CTAs {
padding: 20px;
}


ul.CTAs a {
text-align: center;
font-size: 0.9em !important;
display: block;
border-radius: 5px;
margin-bottom: 5px;
}


a.download {
background: #fff;
color: #7386D5;
}


a.article, a.article:hover {
background: #6d7fcc !important;
color: #fff !important;
}






/* ---------------------------------------------------
CONTENT STYLE
----------------------------------------------------- */
#content {
padding: 20px;
min-height: 100vh;
transition: all 0.3s;
}




/* ---------------------------------------------------
MEDIAQUERIES
----------------------------------------------------- */
@media (max-width: 768px) {
#sidebar {
min-width: 80px;
max-width: 80px;
text-align: center;
margin-left: -80px !important ;
}
a[aria-expanded="false"]::before, a[aria-expanded="true"]::before {
top: auto;
bottom: 5px;
right: 50%;
-webkit-transform: translateX(50%);
-ms-transform: translateX(50%);
transform: translateX(50%);
}
#sidebar.active {
margin-left: 0 !important;
}


#sidebar .sidebar-header h3, #sidebar .CTAs {
display: none;
}


#sidebar .sidebar-header strong {
display: block;
}


#sidebar ul li a {
padding: 20px 10px;
}


#sidebar ul li a span {
font-size: 0.85em;
}
#sidebar ul li a i {
margin-right:  0;
display: block;
}


#sidebar ul ul a {
padding: 10px !important;
}


#sidebar ul li a i {
font-size: 1.3em;
}
#sidebar {
margin-left: 0;
}
#sidebarCollapse span {
display: none;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">


<title>Collapsible sidebar using Bootstrap 3</title>


<!-- Bootstrap CSS CDN -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- Our Custom CSS -->
<link rel="stylesheet" href="style4.css">
</head>
<body>






<div class="wrapper" id="fsbar">
<!-- Sidebar Holder -->
<nav id="sidebar" :class="{ active: isActive }">
<div class="sidebar-header">
<h3>Bootstrap Sidebar</h3>
<strong>BS</strong>
</div>


<ul class="list-unstyled components">
<li class="active">
<a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false">
<i class="glyphicon glyphicon-home"></i>
Home
</a>
<ul class="collapse list-unstyled" id="homeSubmenu">
<li><a href="#">Home 1</a></li>
<li><a href="#">Home 2</a></li>
<li><a href="#">Home 3</a></li>
</ul>
</li>
<li>
<a href="#">
<i class="glyphicon glyphicon-briefcase"></i>
About
</a>
<a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false">
<i class="glyphicon glyphicon-duplicate"></i>
Pages
</a>
<ul class="collapse list-unstyled" id="pageSubmenu">
<li><a href="#">Page 1</a></li>
<li><a href="#">Page 2</a></li>
<li><a href="#">Page 3</a></li>
</ul>
</li>
<li>
<a href="#">
<i class="glyphicon glyphicon-link"></i>
Portfolio
</a>
</li>
<li>
<a href="#">
<i class="glyphicon glyphicon-paperclip"></i>
FAQ
isActive: false, </a>
</li>
<li>
<a href="#">
<i class="glyphicon glyphicon-send"></i>
Contact
</a>
</li>
</ul>


<ul class="list-unstyled CTAs">
<li><a href="https://bootstrapious.com/tutorial/files/sidebar.zip" class="download">Download source</a></li>
<li><a href="https://bootstrapious.com/p/bootstrap-sidebar" class="article">Back to article</a></li>
</ul>
</nav>


<!-- Page Content Holder -->
<div id="content">


<nav class="navbar navbar-default">
<div class="container-fluid">


<div class="navbar-header">
<button type="button" id="sidebarCollapse" class="btn btn-info navbar-btn" @click="toggle()">
<i class="glyphicon glyphicon-align-left"></i>
<span>Toggle Sidebar</span>
</button>
</div>


<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Page</a></li>
<li><a href="#">Page</a></li>
<li><a href="#">Page</a></li>
<li><a href="#">Page</a></li>
</ul>
</div>
</div>
</nav>


<h2>Collapsible Sidebar Using Bootstrap 3</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>


<div class="line"></div>


<h2>Lorem Ipsum Dolor</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>


<div class="line"></div>


<h2>Lorem Ipsum Dolor</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>


<div class="line"></div>


<h3>Lorem Ipsum Dolor</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>










<!-- jQuery CDN -->
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<!-- Bootstrap Js CDN -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


/<script type="text/javascript">
//    $(document).ready(function () {
//       $('#sidebarCollapse').on('click', function () {
//          $('#sidebar').toggleClass('active');
//     });
// }); jquery equivalent to vue
</script>
</body>
</html>

Try :

<template>
<th :class="'initial '+ active" v-on="click: myFilter">
<span class="wkday">M</span>
</th>
</template>


<script lang="ts">


active:string=''
myFilter(){
this.active='active'
}
</script>


<style>
.active{
/***your action***/
}


</style>
@click="$event.target.classList.toggle('active')"
:class="{ active }"
@click="active = !active"
:class="'initial ' + (active ? 'active' : '')"
@click="active = !active"
:class="['initial', { active }]"
@click="active = !active"

Reference link: https://v2.vuejs.org/v2/guide/class-and-style.html

Demo:

new Vue({
el: '#app1'
});


new Vue({
el: '#app2',
data: { active: false }
});


new Vue({
el: '#app3',
data: { active: false }
});


new Vue({
el: '#app4',
data: { active: false }
});
.initial {
width: 300px;
height: 100px;
background: gray;
}


.active {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>


<!-- directly manipulation: not recommended -->
<div id="app1">
<button
class="initial"
@click="$event.target.classList.toggle('active')"
>$event.target.classList.toggle('active')</button>
</div>


<!-- binding by object -->
<div id="app2">
<button
class="initial"
:class="{ active }"
@click="active = !active"
>class="initial" :class="{ active }"</button>
</div>


<!-- binding by expression -->
<div id="app3">
<button
:class="'initial ' + (active ? 'active' : '')"
@click="active = !active"
>'initial ' + (active ? 'active' : '')</button>
</div>


<!-- binding with object combined array -->
<div id="app4">
<button
:class="['initial', { active }]"
@click="active = !active"
>['initial', { active }]</button>
</div>

for nuxt link and bootstrap v5 navbar-nav, I used a child component

             <nuxt-link
@click.prevent.native="isDropdwonMenuVisible = !isDropdwonMenuVisible"
to=""
:title="item.title"
:class="[item.cssClasses, {show: isDropdwonMenuVisible}]"
:id="`navbarDropdownMenuLink-${index}`"
:aria-expanded="[isDropdwonMenuVisible ? true : false]"
class="nav-link dropdown-toggle"
aria-current="page"
role="button"
data-toggle="dropdown"
>
\{\{ item.label }}
</nuxt-link>


data() {
return {
isDropdwonMenuVisible: false
}
},

You don't need to use a prop, you can alternatively call the data into another data variable set using an axios response or any other way you use to pull data into a specified vue component.

You can modify the number 32 below in all places to change the length of text you want to display before and after selecting more/less.

Works with Vue2 & Vue3.

"fw-bold" is a Bootstrap 5 class. It has no affect on this implementation.

props: {
content: Object,
},
data() {
return {
// UX
showComplete: false,
// DATA
shortText: "",
longText: "",
};
},
methods: {
shortenText(body) {
const length = body.length;
if (length >= 32) {
this.shortText = body.slice(0, 32);
this.longText = body.slice(32, -1);
}
},
toggleFull() {
this.showComplete = !this.showComplete;
}
},
created() {
this.shortenText(this.content.body);
},

In the vue template simply do this:

<span>\{\{ shortText }}</span>
<span v-if="showComplete">\{\{ longText }}</span>
<span v-if="!showComplete" class="fw-bold" @click="toggleFull"> more...</span>
<span v-if="showComplete" class="fw-bold" @click="toggleFull"> less...</span>

This is how you would achieve that one with Vue3 + Composition API

<script setup>
import { ref } from 'vue'
  

const isTextRed = ref(false)
function toggleClass() {
isTextRed.value = !isTextRed.value
}
</script>


<template>
<h1 :class="isTextRed && 'fancy-color'">Hi community 👋🏻</h1>
<button @click="toggleClass">Toggle color</button>
</template>


<style scoped>
.fancy-color {
color: Coral;
}
</style>

Here is a playground.