首页 > 解决方案 > 在Vue中的网格中单击特定项目时添加类

问题描述

我有一个项目网格(在 flexbox 中创建以便使用 v-for 循环)。我想.selected在单击列表中的特定项目时添加类。存在一个问题,即每列中的 item 获取的类应该只应用于单个元素。我应该怎么做才能让它工作?

网格:

new Vue({
  el: "#app",
  data: {
    rows: 8,
    items: [
      {
        selected: false
      },
      {
        selected: false
      },
      {
        selected: false
      },
      {
        selected: false
      },
      {
        selected: false
      },
      {
        selected: false
      },
      {
        selected: false
      }
    ]
  }
})
.app > ul {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 4vh;
  padding-bottom: 4vh;
  border-bottom: 1px solid gray;
}
.app > ul > li.row > ul {
  display: flex;
  margin: 8px 0;
}
.app > ul > li.row > ul li {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background-color: transparent;
  border: 3px solid gray;
  margin: 0 8px;
}
.app > ul > li.row > ul li.selected {
  background-color: gray;
}
ul {
 list-style-type: none;
 padding: 0;
 margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="app">
  <ul>
    <li v-for="row in rows" class="row">
      <ul>
        <li v-for="item, index in items" :key="index" :class="{ selected: item.selected }" @click="item.selected = !item.selected"></li>
      </ul>
    </li>
  </ul>
</div>

标签: javascriptvue.js

解决方案


你的想法是正确的。问题出在你的数据结构上。

您只有 7 个项目 - 但您希望它们表现得像 8 行,每行 7 个项目。您的数据对象应该反映您在 DOM 中循环的结构。

这样的事情将是你所追求的:

new Vue({
  el: "#app",
  data: {
    rows: [
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      },
      {
        items: [
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          },
          {
            selected: false
          }
        ]
      }
    ]
    
  }
})
.app > ul {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 4vh;
  padding-bottom: 4vh;
  border-bottom: 1px solid gray;
}
.app > ul > li.row > ul {
  display: flex;
  margin: 8px 0;
}
.app > ul > li.row > ul li {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background-color: transparent;
  border: 3px solid gray;
  margin: 0 8px;
}
.app > ul > li.row > ul li.selected {
  background-color: gray;
}
ul {
 list-style-type: none;
 padding: 0;
 margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="app">
  <ul>
    <li v-for="(row, rowIndex) in rows" class="row">
      <ul>
        <li v-for="(item, index) in row.items" :key="index + '_' + rowIndex" :class="{ selected: item.selected }" @click="item.selected = !item.selected"></li>
      </ul>
    </li>
  </ul>
</div>

编辑:您不必对这些值进行硬编码。如果您选择,您可以使用Vue.$set().

Vue.$set()在组件中使用mounted()钩子的示例:

export default {
  mounted () {
    const rows = 8
    const itemsPerRow = 7

    for (let r = 0; r < rows; r++) {
      let row = {
        items: []
      }

      for (let i = 0; i < itemsPerRow; i++) {
        row.items.push({
          selected: false
        })
      }

      this.$set(this.rows, r, row)

    }
  },

  data () {
    return {
      rows: []
    }
  }
}

推荐阅读