【问题标题】:Vuejs toggle class in v-forv-for 中的 Vuejs 切换类
【发布时间】:2019-01-14 09:57:22
【问题描述】:

我正在使用 v-for 循环制作一个项目列表。我有一些来自服务器的 API 数据。

items: [
   {
       foo: 'something',
       number: 1
   },
   {
       foo: 'anything',
       number: 2
   }
]

我的模板是:

<div v-for(item,index) in items @click=toggleActive>
     {{ item.foo }} 
     {{ item.number }} 
</div>

JS:

methods: {
    toggleActive() {
        //
    }
}

如何使用 :class={active : something} 切换活动类? P.S 我在 items 中没有布尔值

【问题讨论】:

  • 不移动单独组件中的项目

标签: class dynamic vue.js toggle v-for


【解决方案1】:

你可以尝试实现类似的东西:

<div 
  v-for="(item, index) in items"
  v-bind:key="item.id" // or alternativelly use `index`.
  v-bind:class={'active': activeItem[item.id]}
  @click="toggleActive(item)"
>

JS:

data: () => ({ 
  activeItem: {}, 
}),

methods: {
  toggleActive(item) {
    if (this.activeItem[item.id]) {
      this.removeActiveItem(item);

      return;
    }

    this.addActiveItem(item);
  },
  addActiveItem(item) {
    this.activeItem = Object.assign({},
      this.activeItem,
      [item.id]: item,
    );
  },
  removeActiveItem(item) {
    delete this.activeItem[item.id];
    this.activeItem = Object.assign({}, this.activeItem);
  },
}

【讨论】:

  • 工作不正确。当我尝试单击另一个项目时,以前的课程不受欢迎。我需要选择多个元素,然后在第二次单击项目时,取消固定的活动类
  • this.activeItem underfined,addActiveItem 方法中的“[item.id]: item”是什么?
  • 有一个错字。 [item.id]: item 基本上是一种在对象中动态设置属性键的方法。它是 ES6 版本中引入的一个新的 Javascript 功能,称为Computed property names。因此,如果item.id 的值例如是“fooText”,则该对象将看起来像{ 'fooText': item }。进一步阅读:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…stackoverflow.com/questions/2462800/…
【解决方案2】:

我遇到了同样的问题,虽然要找到很多有用的信息并不容易,但实现起来却相对简单。我有一个商店列表,它们映射到一种可点击按钮的标签云。单击其中一个时,“已添加”类将添加到链接中。标记:

<div class="col-sm-10">
    <a href="#" class="tagCloud" v-for="store in stores" v-on:click="toggleAdd(store)" v-bind:class="{ 'added': selectedStoreIds.indexOf(store.id) !== -1 }">{{ store.name }}</a>
</div>

以及相关的脚本(在本例中为 TypeScript)。 toggleAddselectedStoreIds 中添加或删除store id,并且类会自动更新:

new Vue({
    el: "#productPage",
    data: {
        stores: [] as StoreModel[],
        selectedStoreIds: [] as string[],
    },
    methods: {
        toggleAdd(store: StoreModel) {
            let idx = this.selectedStoreIds.indexOf(store.id);
            if (idx !== -1) {
                this.selectedStoreIds.splice(idx, 1);
            } else {
                this.selectedStoreIds.push(store.id);
            }
    },
    async mounted () {
        this.stores = await this.getStores(); // ajax request to retrieve stores from server
    }
});

Marlon Barcarol's answer 帮我解决了这个问题。

【讨论】:

    【解决方案3】:

    分两步完成。

    1) 在父组件中创建 v-for 循环,比如

    <myComponent v-for="item in itemsList"/>
    
    data() {
      return {
        itemsList: ['itemOne', 'itemTwo', 'itemThree']
      }
    }
    

    2) 使用所有必要的逻辑创建子 myComponent 本身

    <div :class="someClass" @click="toggleClass"></div>
    
    data(){
      return {
        someClass: "classOne"
      }
    },
    methods: {
      toggleClass() {
        this.someClass = "classTwo";
      }
    }
    

    这样 v-for 循环中的所有元素都会有独立的逻辑,不涉及兄弟元素

    【讨论】:

      【解决方案4】:

      我正在做一个项目,我有同样的要求,这里是代码:

      你可以忽略 CSS 并选择 vue 逻辑:)

      new Vue({
        el: '#app',
        data: {
          items: [{ title: 'Finance', isActive: false }, { title: 'Advertisement', isActive: false }, { title: 'Marketing', isActive: false }],
        },
      })
      body{background:#161616}.p-wrap{color:#bdbdbd;width:320px;background:#161616;min-height:500px;border:1px solid #ccc;padding:15px}.angle-down svg{width:20px;height:20px}.p-card.is-open .angle-down svg{transform:rotate(180deg)}.c-card,.p-card{background:#2f2f2f;padding:10px;border-bottom:1px solid #666}.c-card{height:90px}.c-card:first-child,.p-card:first-child{border-radius:8px 8px 0 0}.c-card:first-child{margin-top:10px}.c-card:last-child,.p-card:last-child{border-radius:0 0 8px 8px;border-bottom:none}.p-title .avatar{background-color:#8d6e92;width:40px;height:40px;border-radius:50%}.p-card.is-open .p-title .avatar{width:20px;height:20px}.p-card.is-open{padding:20px 0;background-color:transparent}.p-card.is-open:first-child{padding:10px 0 20px}.p-card.is-open:last-child{padding:20px 0 0}.p-body{display:none}.p-card.is-open .p-body{display:block}.sec-title{font-size:12px;margin-bottom:10px}
      <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
      
      <div id="app" class="p-5">
        <div class="p-wrap mx-auto">
          <div class="sec-title">NEED TO ADD SECTION TITLE HERE</div>
          <div>
            <div v-for="(item, index) in items" v-bind:key="index" class="p-card" v-bind:class="{'is-open': item.isActive}"
              v-on:click="item.isActive = !item.isActive">
              <div class="row p-title align-items-center">
                <div class="col-auto">
                  <div class="avatar"></div>
                </div>
                <div class="col pl-0">
                  <div class="title">{{item.title}}</div>
                </div>
                <div class="col-auto">
                  <div class="angle-down">
                    <svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="angle-down" role="img"
                      xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"
                      class="svg-inline--fa fa-angle-down fa-w-10 fa-3x">
                      <path fill="currentColor"
                        d="M151.5 347.8L3.5 201c-4.7-4.7-4.7-12.3 0-17l19.8-19.8c4.7-4.7 12.3-4.7 17 0L160 282.7l119.7-118.5c4.7-4.7 12.3-4.7 17 0l19.8 19.8c4.7 4.7 4.7 12.3 0 17l-148 146.8c-4.7 4.7-12.3 4.7-17 0z"
                        class=""></path>
                    </svg>
                  </div>
                </div>
              </div>
              <div class="p-body">
                <div class="c-card"></div>
                <div class="c-card"></div>
                <div class="c-card"></div>
              </div>
            </div>
          </div>
        </div>
      </div>

      【讨论】:

        猜你喜欢
        • 2021-02-21
        • 2019-08-06
        • 2020-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多