javascript - 在 Vue 网格中单击特定项目时添加类

标签 javascript vue.js

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

网格:

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>

最佳答案

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

您只有 7 个项目 - 但您希望它们的行为类似于 8 行,每行 7 个项目。您的数据对象应该反射(reflect)您在 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() 在组件 Mounted() (或其他合适的事件)上循环生成它们。

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

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: []
    }
  }
}

关于javascript - 在 Vue 网格中单击特定项目时添加类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56441037/

相关文章:

javascript - 如何从 JSON 响应中获取逗号分隔的列表?

javascript - Vue.js:如何对页面滚动使用react?

javascript - 在 anchor 上显示/ overflow hidden div

vue.js - 是否可以将数据从一个 vue 应用程序推送到另一个应用程序?

javascript - 如何在 filepond 中添加下载图像或 Pdf/任何文档?

javascript - 选中 Vuejs Vuetify 时更改复选框图标

javascript - 如何将字符串导出到另一个 Vue 文件?

javascript - 删除 fullCalendar 中的所有事件源

javascript - react-native 中 TextInput 的焦点样式

javascript - 使用 jQuery 将外部 URL 加载到 div