Vue.js перемикає клас на клік


77

Як відбувається перемикання класу у 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>      

Це потрібно перемикати, тобто кожного разу, коли натискається, йому потрібно додавати / видаляти клас.

Відповіді:


76

Ви можете мати активний клас залежно від булевого значення даних:

<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
    }
  }
})

34
з якихось причин v-class="active: isActive"мій додаток виходить з ладу, але v-bind:class="{ active: isActive }" працює для мене. Сподіваюся, це комусь корисно.
Фрейзер Кіркман,

6
схоже, синтаксис весь час змінюється за допомогою vue. У 2. * ви також можете просто зробити:class="..."
rzb

6
Я роблю це у vue.js-2. Коли я натискаю один рядок, activeклас застосовується до всіх рядків. Я щось роблю не так?
Syed

1
ви можете зробити кожен рядок своїм компонентом, який відповідає за його isActiveвласність
Дуглас Сезар

2
всі приклади для встановлення активного класу стосуються лише одного елемента. Що робити, якби у мене було кілька візуалізованих I v-for, як тоді я надав би активний клас за останнім натисканням цього списку. <a href="#" @click="switchRoom(room)" class="rooms" :class="{currentRoom: room.isActive}" v-for="(room, index) in allRooms" :key="index">{{ room.name }} </a>
Акін Хван,

76

Без необхідності методу:

// html element
<div id="mobile-toggle"
 v-bind:class="{ active: showMobileMenu }"
 v-on:click="showMobileMenu = !showMobileMenu">
</div>

//in your vue.js app
data: {
    showMobileMenu: false
}

2
@ConnorLeech <li v-for="(item, index) in items" :key="item.id" v-bind:class="{ active: active == item }" @click="active = item">Потім додати .active {styles}і покласти його в<ul>
nbixler

А що активне? showMobileMenuє змінною, але що це за клас?
rjurney

34

Якщо вам не потрібно отримувати доступ до перемикача ззовні елемента, цей код працює без змінної даних:

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

1
Хотіла цього. Простий і загальний.
Ron16,

1
Я якийсь новачок у Vue, але з цим рішенням я зіткнувся з проблемою. Коли я додаю @ click = "e => e.target.classList.toggle ('active')" на батьківський елемент картки vue-bootstrap, відбувається те, що вся карта не отримує перемикач CSS, натомість клас застосовується на клацання частин картки, і ви можете перемикати кілька на одній картці.
Kevz

1
@Kevz, що насправді є обмеженням цього підходу - він лише перемикає ціль події, яка є найбільш вкладеним <a> або <button>, на якому ви натискаєте. Для вашої проблеми я б замість цього використав одне з рішень змінних даних на цій сторінці.
Фабіан фон Еллерц

23

Ця відповідь актуальна для Vue.js version 2

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

Решта відповідей Дугласа все ще застосовується (налаштування нового екземпляра Vue за допомогою isActive: falseтощо).

Відповідні документи: https://vuejs.org/v2/guide/class-and-style.html#Object-Syntax та https://vuejs.org/v2/guide/events.html#Method-Event-Handlers


коли я натискаю один рядок, activeклас застосовується до всіх рядків. Я щось роблю не так?
Syed

та сама проблема тут, це працює лише в тому випадку, якщо в компоненті є лише один клікаючий елемент. а що, якщо компонент має кілька клікабельних елементів?
Кокодоко,

Якщо ви задасте нове запитання, я можу розглянути його. Подяка
NateW

15

Цей приклад - використання списків: при натисканні клавіші li воно стає червоним

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;
}

Скрипка:

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


7

На додаток до відповіді NateW, якщо у назві вашого класу css є дефіси, вам слід обернути цей клас у (одинарні) лапки:

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

 <span class="wkday">M</span>
 </th>

Докладніше про цю тему див. У цій темі.


5

1.

@click="$event.target.classList.toggle('active')"

2.

:class="{ active }"
@click="active = !active"

3.

:class="'initial ' + (active ? 'active' : '')"  
@click="active = !active"

4.

:class="['initial', { active }]"  
@click="active = !active"

Довідкове посилання: https://vuejs.org/v2/guide/class-and-style.html

Демо:

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>


3

Якщо вам потрібно більше 1 класу

Ви можете зробити це:

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

data: {
  showStar: true
}

Зверніть увагу на окремі лапки навколо класів!

Завдяки всім іншим рішенням.


1

У мене є рішення, яке дозволяє перевірити наявність різних значень реквізиту, і, таким чином, різні <th>елементи стануть активними / неактивними. Використання синтаксису vue 2.

<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
    }
  }
})

0

для nuxt link та bootstrap v5 navbar-nav я використав дочірній компонент

             <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
    }
  },

-1

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>


-1

Спробуйте:

<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>    

1
Окрім фрагмента коду, додайте коротке пояснення, чому це вирішує проблему.
Alexander van Oostenrijk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.