【问题标题】:How to apply toggling / styles on a particular clicked card only in vue.js?如何仅在 vue.js 中对特定点击的卡片应用切换/样式?
【发布时间】:2021-09-20 19:08:46
【问题描述】:

我开发了一个页面 DisplayBooks.vue,它负责显示来自后端 API 的响应的书籍,基于它将显示在我的 UI 页面中的数据,在我的 UI 页面中,每张卡片都包含两个按钮(添加到袋子和添加TO BAG)当用户点击任何卡片添加到袋子按钮时,它会隐藏添加到袋子并仅在特定点击的卡片上显示添加到袋子按钮,请帮助我实现这个目标。

DisplayBooks.vue

<template>
<div class="carddisplay-section">
    <div v-for="book in books" :key="book.id" class="card book">
        <div class="image-section">
            <div class="image-container">
                <img  v-bind:src="book.file" />
            </div>
        </div>
        <div class="title-section">
            {{book.name}}
        </div>
        <div class="author-section">
            by {{book.author}}
        </div>
        <div class="price-section">
            Rs. {{book.price}}<label class="default">(2000)</label>
            <button v-if="flag" class="btn-grp" type="submit" @click="handlesubmit();Togglebtn();">close</button>
        </div>
        <div class="buttons">
            <div class="button-groups">
                <button type="button"  class="AddBag">Add to Bag</button>
                
            </div>
            <div  class="AddedBag">
                <button class="big-btn">Added to Bag</button>
            </div>
        </div>
    </div>

</div>
</template>

<script>
import service from '../service/User'

export default {
    data() {
        return {
           
            flag: true,
            state: true,
            clickedCard: '',
            books: [{
                id: 0,
                file: 'https://images-na.ssl-images-amazon.com/images/I/41MdP5Tn0wL._SX258_BO1,204,203,200_.jpg',
                name: 'Dont Make me think',
                author: 'Sai',
                price: '1500'
            }, ]
        }
    },
    methods: {
       
        
        flip() {
            this.state = !this.state;
        },
        Togglebtn() {
            this.flag = !this.flag;
        },
        handlesubmit() {
            service.userDisplayBooks().then(response => {
                this.books.push(...response.data);     
            })
        },
    }
}
</script>

<style lang="scss" scoped>
    @import "@/styles/DisplayBooks.scss";
</style>

DisplayBooks.scss

@import "colors";
.carddisplay-section {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    align-content: space-around;
    gap: 10px;
}
.card:hover{
    box-shadow:0.6px 0.6px 0.6px 0.6px rgb(173, 206, 206);
}
.card {
    margin-top: 55px;
    margin-left: 110px;
    background:$pink;
    // width: 235px;
    // height: 275px;
    width: 235px;
height: 315px;
    background: $pale_white 0% 0% no-repeat padding-box;
    border: 1px solid $border_clr;
    border-radius: 3px;
    opacity: 1;
}

.image-section {
    width: 233px;
    height: 172px;
    background: #F5F5F5 0% 0% no-repeat padding-box;
    border-radius: 2px 2px 0px 0px;
    opacity: 1;
}

img{
    margin-left: 67px;
    margin-top: 17px;
    width: 105px;
    height: 135px;
    opacity: 1;
    border:none;
}

.title-section {
    text-align: left;
    font: normal normal normal 14px/19px Roboto;
    letter-spacing: 0.2px;
    color: $light_black;
    opacity: 1;
    margin-left: 20px;
    margin-top: 3px;
    width: 130px;
    height: 19px;
    text-transform: capitalize;
}

.author-section {
    text-align: left;
    font: normal normal normal 13px/13px Roboto;
    letter-spacing: 0px;
    color: $light_grey;
    opacity: 1;
    width: 123px;
    height: 13px;
    margin-left: 20px;
    margin-top: 7px;
}

.price-section {
    text-align: left;
    font: normal normal bold 12px/16px Roboto;
    letter-spacing: 0px;
    color: $light_black;
    opacity: 1;
    margin-left: 20px;
    height: 16px;
    margin-top: 26px;
    display: flex;
    justify-content: flex-start;

}

label {
    text-decoration-line: line-through;
    font: normal normal normal 10px/13px Roboto;
    letter-spacing: 0px;
    color: $light_grey;
    opacity: 1;
    width: 36px;
    height: 13px;
    margin-top: 2.5px;
    margin-left: 1em;
}

button[type="submit"] {
    border: none;
    padding-left: 65px;
    background: none;
    font-size: 15;
}
.button-groups{
    display:flex;
    margin-top:8px;
}
.AddBag{
    background: #A03037 0% 0% no-repeat padding-box;
    border-radius: 2px;
    opacity: 1;
    width: 93px;
    height: 29px;
    margin-left:20px;
    color: #FFFFFF;
    text-transform: uppercase;
    opacity: 1;
    font-size: small;
}
.wishlist{
    margin-left:4px;
    color: #FFFFFF;
    text-transform: uppercase;
    opacity: 1;
    font-size: small;
    border: 1px solid #7c7a7a;
    border-radius: 2px;
    opacity: 1;
    color: #0A0102;
    width:93px;
}
.big-btn{
    width: 191px;
height: 29px;
margin-left:20px;
background: #3371B5 0% 0% no-repeat padding-box;
border-radius: 2px;
opacity: 1;
color:#FFFFFF;
}
   

【问题讨论】:

    标签: javascript css vue.js vuejs2


    【解决方案1】:

    添加另一个数组,其中包含通过单击按钮添加到 BAG 添加的书籍 ID,然后使用 v-if/v-else 进行条件渲染:

        data() {
            return {
               
                flag: true,
                state: true,
                clickedCard: '',
                addedBooks:[],
                books: [....]
            }
        },
    

    在模板中:

        <div class="buttons">
                <div class="button-groups" v-if="!addedBooks.includes(book.id)">
                    <button type="button"  @click="addedBooks.push(book.id)"  class="AddBag">Add to Bag</button>
                    
                </div>
                <div  class="AddedBag" v-else>
                    <button class="big-btn" @click="addedBooks=addedBooks.filter(id=>id!==book.id)">Added to Bag</button>
                </div>
            </div>
    

    示例

    new Vue({
      el: "#app",
    
      data() {
        return {
    
          flag: true,
          state: true,
          clickedCard: '',
          addedBooks: [],
          books: [{
              id: 0,
              file: 'https://images-na.ssl-images-amazon.com/images/I/41MdP5Tn0wL._SX258_BO1,204,203,200_.jpg',
              name: 'Dont Make me think',
              author: 'Sai',
              price: '1500'
            },
            {
              id: 1,
              file: 'https://images-na.ssl-images-amazon.com/images/I/41MdP5Tn0wL._SX258_BO1,204,203,200_.jpg',
              name: 'Dont Make me think',
              author: 'Sai',
              price: '1500'
            },
    
          ]
        }
      },
      methods: {
    
    
        flip() {
          this.state = !this.state;
        },
        Togglebtn() {
          this.flag = !this.flag;
        },
    
      }
    })
    .carddisplay-section {
      display: flex;
      align-items: flex-start;
      flex-wrap: wrap;
      align-content: space-around;
      gap: 10px;
    }
    
    .card:hover {
      box-shadow: 0.6px 0.6px 0.6px 0.6px rgb(173, 206, 206);
    }
    
    .card {
      margin-top: 55px;
      margin-left: 110px;
      background: $pink;
      // width: 235px;
      // height: 275px;
      width: 235px;
      height: 315px;
      background: $pale_white 0% 0% no-repeat padding-box;
      border: 1px solid $border_clr;
      border-radius: 3px;
      opacity: 1;
    }
    
    .image-section {
      width: 233px;
      height: 172px;
      background: #F5F5F5 0% 0% no-repeat padding-box;
      border-radius: 2px 2px 0px 0px;
      opacity: 1;
    }
    
    img {
      margin-left: 67px;
      margin-top: 17px;
      width: 105px;
      height: 135px;
      opacity: 1;
      border: none;
    }
    
    .title-section {
      text-align: left;
      font: normal normal normal 14px/19px Roboto;
      letter-spacing: 0.2px;
      color: $light_black;
      opacity: 1;
      margin-left: 20px;
      margin-top: 3px;
      width: 130px;
      height: 19px;
      text-transform: capitalize;
    }
    
    .author-section {
      text-align: left;
      font: normal normal normal 13px/13px Roboto;
      letter-spacing: 0px;
      color: $light_grey;
      opacity: 1;
      width: 123px;
      height: 13px;
      margin-left: 20px;
      margin-top: 7px;
    }
    
    .price-section {
      text-align: left;
      font: normal normal bold 12px/16px Roboto;
      letter-spacing: 0px;
      color: $light_black;
      opacity: 1;
      margin-left: 20px;
      height: 16px;
      margin-top: 26px;
      display: flex;
      justify-content: flex-start;
    }
    
    label {
      text-decoration-line: line-through;
      font: normal normal normal 10px/13px Roboto;
      letter-spacing: 0px;
      color: $light_grey;
      opacity: 1;
      width: 36px;
      height: 13px;
      margin-top: 2.5px;
      margin-left: 1em;
    }
    
    button[type="submit"] {
      border: none;
      padding-left: 65px;
      background: none;
      font-size: 15;
    }
    
    .button-groups {
      display: flex;
      margin-top: 8px;
    }
    
    .AddBag {
      background: #A03037 0% 0% no-repeat padding-box;
      border-radius: 2px;
      opacity: 1;
      width: 93px;
      height: 29px;
      margin-left: 20px;
      color: #FFFFFF;
      text-transform: uppercase;
      opacity: 1;
      font-size: small;
    }
    
    .wishlist {
      margin-left: 4px;
      color: #FFFFFF;
      text-transform: uppercase;
      opacity: 1;
      font-size: small;
      border: 1px solid #7c7a7a;
      border-radius: 2px;
      opacity: 1;
      color: #0A0102;
      width: 93px;
    }
    
    .big-btn {
      width: 191px;
      height: 29px;
      margin-left: 20px;
      background: #3371B5 0% 0% no-repeat padding-box;
      border-radius: 2px;
      opacity: 1;
      color: #FFFFFF;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <div class="carddisplay-section">
        <div v-for="book in books" :key="book.id" class="card book">
          <div class="image-section">
            <div class="image-container">
              <img v-bind:src="book.file" />
            </div>
          </div>
          <div class="title-section">
            {{book.name}}
          </div>
          <div class="author-section">
            by {{book.author}}
          </div>
          <div class="price-section">
            Rs. {{book.price}}<label class="default">(2000)</label>
            <button v-if="flag" class="btn-grp" type="submit" @click="">close</button>
          </div>
          <div class="buttons">
            <div class="button-groups" v-if="!addedBooks.includes(book.id)">
              <button type="button" @click="addedBooks.push(book.id)" class="AddBag">Add to Bag</button>
    
            </div>
            <div class="AddedBag" v-else>
              <button class="big-btn" @click="addedBooks=addedBooks.filter(id=>id!==book.id)">Added to Bag</button>
            </div>
          </div>
        </div>
    
      </div>
    </div>

    【讨论】:

    • 点击添加到袋子按钮它应该隐藏并显示添加到袋子功能不起作用
    • 请澄清更多
    • 当用户点击添加到袋子按钮时,它隐藏添加到袋子按钮并显示添加到袋子按钮直到它工作,只有当用户再次点击添加到袋子按钮时才会这样它应该返回到 ADD TO BAG 按钮(意味着 ADDED TO BAG 按钮应该被隐藏)
    • addedBooks 填充了添加的ID?
    • 试用&lt;button class="big-btn" @click="addedBooks=addedBooks.filter(id=&gt;id!==book.id)"&gt;Added to Bag&lt;/button&gt;
    猜你喜欢
    • 2021-09-20
    • 1970-01-01
    • 2017-10-01
    • 2018-08-09
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2021-09-06
    相关资源
    最近更新 更多