【问题标题】:Vue.js toggle class on clickVue.js 在点击时切换类
【发布时间】:2017-10-01 03:40:18
【问题描述】:

如何在 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
    }
  }
});

当我点击&lt;th&gt; 标签时,我想将active 应用为一个类,如下所示:

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

这需要切换,即每次单击它都需要添加/删除类。

【问题讨论】:

    标签: css vue.js


    【解决方案1】:

    您可以让活动类依赖于布尔数据值:

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

    【讨论】:

    • 由于某种原因v-class="active: isActive" 使我的应用程序崩溃,但v-bind:class="{ active: isActive }" 对我有用。希望这对某人有帮助。
    • vue 的语法似乎一直在变化。在 2.* 你也可以只做:class="..."
    • 我是在 vue.js-2 中做的。当我单击一行时,active 类将应用于所有行。我做错了吗?
    • 您可以将每一行设为自己的组件,该组件负责自己的isActive 属性
    • 所有设置 Active 类的示例都只针对一项,如果我有多个 I v-for 渲染,那么我将如何在此列表中最近单击的一个上赋予 Active 类。 &lt;a href="#" @click="switchRoom(room)" class="rooms" :class="{currentRoom: room.isActive}" v-for="(room, index) in allRooms" :key="index"&gt;{{ room.name }} &lt;/a&gt;
    【解决方案2】:

    这个答案与Vue.js version 2相关

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

    Douglas 的其余答案仍然适用(使用isActive: false 等设置新的 Vue 实例)。

    相关文档:https://vuejs.org/v2/guide/class-and-style.html#Object-Syntax 和 https://vuejs.org/v2/guide/events.html#Method-Event-Handlers

    【讨论】:

    • 当我单击一行时,active 类将应用于所有行。我做错了吗?
    • 这里有同样的问题,这仅在组件中只有一个可点击元素时才有效。如果一个组件有多个可点击元素怎么办?
    • 如果您提出新问题,我可以调查一下。谢谢
    【解决方案3】:

    除了 NateW 的回答之外,如果您的 css 类名称中有连字符,则应该将该类包含在(单)引号内:

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

    有关该主题的更多信息,请参阅 this 主题。

    【讨论】:

      【解决方案4】:

      无需方法:

      // 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>
      
      //in your vue.js app
      data: {
          showMobileMenu: false
      }
      

      【讨论】:

      • @ConnorLeech &lt;li v-for="(item, index) in items" :key="item.id" v-bind:class="{ active: active == item }" @click="active = item"&gt; 然后加上.active {styles} 放在&lt;ul&gt;里面
      • 什么是活跃的? showMobileMenu 是一个变量,但类是什么?
      • @rjurney active 是 CSS 类。最好这样写:'active': showMobileMenu,但它是一样的。
      【解决方案5】:

      我有一个解决方案,允许您检查道具的不同值,因此不同的&lt;th&gt; 元素将变为活动/不活动。使用 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
          }
        }
      })
      

      【讨论】:

        【解决方案6】:

        如果您需要 1 个以上的课程

        你可以这样做:

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

        注意类周围的单引号 '!

        感谢其他人的解决方案。

        【讨论】:

          【解决方案7】:

          如果您不需要从元素外部访问切换,则此代码无需数据变量即可工作:

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

          【讨论】:

          • 想要这个。简单而通用。
          • 我对 Vue 有点陌生,但是我在使用这个解决方案时遇到了一个问题。当我在 vue-bootstrap 卡父元素上添加 @click="e => e.target.classList.toggle('active')" 时,会发生整个卡没有获得 CSS 切换,而是类适用于您点击卡片的一部分,您可以在一张卡片中切换多个。
          • @Kevz 这确实是这种方法的一个限制 - 它只切换事件目标,这是您单击的最嵌套的 或
          • 如果您不介意 Vue 在两个元素上切换类的怪癖,您可以在 target 之后添加 parentNode。我发现将 pointer-events: none 添加到子元素的 CSS 中最简单。
          【解决方案8】:

          这个例子是使用列表:当点击某些 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/

          【讨论】:

          • 非常感谢,这对我有帮助。
          【解决方案9】:

          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>

          【讨论】:

            【解决方案10】:

            试试:

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

            【讨论】:

            • 除了代码sn-p,请添加一个简短的解释说明为什么这样可以解决问题。
            【解决方案11】:

            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>

            【讨论】:

              【解决方案12】:

              对于 nuxt 链接和 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
                  }
                },
              

              【讨论】:

                猜你喜欢
                • 2018-08-09
                • 2017-12-11
                • 1970-01-01
                • 2019-08-06
                • 1970-01-01
                • 1970-01-01
                • 2018-02-27
                • 1970-01-01
                相关资源
                最近更新 更多