(Vuetify) Switch 扩展了数据迭代器的所有元素,而不仅仅是一个

发布于 2025-01-10 18:39:35 字数 9403 浏览 0 评论 0原文

我在 Vuetify 中有一个动态填充的数据迭代器。每个项目都显示有关产品的一些信息以及图像。在卡片展开之前,信息将被隐藏。每张卡都包含一个用于扩展该卡的开关。但每次切换都会立即展开所有卡。我无法确定解决方案。 Vuetify API 文档并没有多大帮助。

商店显示.vue:

<template>
  <v-container fluid>
    <v-data-iterator
      :items="items"
      :items-per-page.sync="itemsPerPage"
      :page.sync="page"
      :search="search"
      :sort-by="sortBy.toLowerCase()"
      :sort-desc="sortDesc"
      hide-default-footer
    >
      <template v-slot:header>
        <v-toolbar
          dark
          color="blue darken-3"
          class="mb-1"
        >
          <v-text-field
            v-model="search"
            clearable
            flat
            solo-inverted
            hide-details
            prepend-inner-icon="mdi-magnify"
            label="Search"
          ></v-text-field>
          <template v-if="$vuetify.breakpoint.mdAndUp">
            <v-spacer></v-spacer>
            <v-select
              v-model="sortBy"
              flat
              solo-inverted
              hide-details
              :items="keys"
              prepend-inner-icon="mdi-magnify"
              label="Sort by"
            ></v-select>
            <v-spacer></v-spacer>
            <v-btn-toggle
              v-model="sortDesc"
              mandatory
            >
              <v-btn
                large
                depressed
                color="blue"
                :value="false"
              >
                <v-icon>mdi-arrow-up</v-icon>
              </v-btn>
              <v-btn
                large
                depressed
                color="blue"
                :value="true"
              >
                <v-icon>mdi-arrow-down</v-icon>
              </v-btn>
            </v-btn-toggle>
          </template>
        </v-toolbar>
      </template>

      <template v-slot:default="{ items, isExpanded, expand }">
        <v-row>
          <v-col
            v-for="item in items"
            :key="item.name"
            cols="12"
            sm="6"
            md="4"
            lg="3"
          >
            <v-card>
              <v-container class="productCard" style="text-align:center" >
                <div class="img-cont" >
                <v-img
                  contain
                  :src="require('@/assets/'+ item.productImage +'.jpg')" alt="loading..."
                  max-height="200px"
                  />
              </div>
                <v-card-title class="subheading font-weight-bold">
                  <v-row >
                    <v-col>
                      <h4>{{item.name}}</h4>
                  </v-col>
                  </v-row>
                </v-card-title>
                <v-row>
                  <v-col>
                    <h4>{{item.price}}</h4>
                  </v-col>
                </v-row>
              </v-container>
              <v-switch
                :input-value="isExpanded(item)"
                :label="isExpanded(item) ? 'Expanded' : 'Closed'"
                class="pl-4 mt-0"
                @change="(v) => expand(item, v)"
              ></v-switch>
              <v-divider></v-divider>

              <v-list
                v-if="isExpanded(item)"
                dense
              >
                <v-list-item>
                  <v-list-item-content>Description:</v-list-item-content>
                  <v-list-item-content class="align-end">
                    {{ item.description }}
                  </v-list-item-content>
                </v-list-item>
                <v-list-item>
                  <v-list-item-content>Retailer:</v-list-item-content>
                  <v-list-item-content class="align-end">
                    {{item.retailer}}
                  </v-list-item-content>
                </v-list-item>
              </v-list>
            </v-card>
          </v-col>
        </v-row>
      </template>

      <template v-slot:footer>
        <v-row
          class="mt-2"
          align="center"
          justify="center"
        >
          <span class="grey--text">Items per page</span>
          <v-menu offset-y>
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                dark
                text
                color="primary"
                class="ml-2"
                v-bind="attrs"
                v-on="on"
              >
                {{ itemsPerPage }}
                <v-icon>mdi-chevron-down</v-icon>
              </v-btn>
            </template>
            <v-list>
              <v-list-item
                v-for="(number, index) in itemsPerPageArray"
                :key="index"
                @click="updateItemsPerPage(number)"
              >
                <v-list-item-title>{{ number }}</v-list-item-title>
              </v-list-item>
            </v-list>
          </v-menu>

          <v-spacer></v-spacer>

          <span
            class="mr-4
            grey--text"
          >
            Page {{ page }} of {{ numberOfPages }}
          </span>
          <v-btn
            fab
            dark
            color="blue darken-3"
            class="mr-1"
            @click="formerPage"
          >
            <v-icon>mdi-chevron-left</v-icon>
          </v-btn>
          <v-btn
            fab
            dark
            color="blue darken-3"
            class="ml-1"
            @click="nextPage"
          >
            <v-icon>mdi-chevron-right</v-icon>
          </v-btn>
        </v-row>
      </template>
    </v-data-iterator>
  </v-container>
</template>

<script>
  export default {
    data () { 
      return {
        itemsPerPageArray: [4, 8, 12],
        search: '',
        filter: {},
        sortDesc: false,
        page: 1,
        itemsPerPage: 4,
        sortBy: 'name',
        keys: [
          'Name',
          'Price',
          'Description',
          'Retailer'
        ],
        items: [
          {
            name: '6 foot HDMI cable',
            price: '$' + 19.99,
            description: '6 foot HDMI cable',
            retailer: 'Jones Audio/Visual',
            productImage: 'hdmicable'
          },
          {
            name: '23 inch Monitor',
            price: '$' + 199.99,
            description: '23 inch Monitor',
            retailer: 'Samsung',
            productImage: 'monitor'
          },
          {
            name: 'RJ45 Connectors (Pack of 30)',
            price: '$' + 14.99,
            description: 'CAT-5 Connectors (Pack of 30)',
            retailer: 'Electronics Emporium',
            productImage: 'RJ45Connector'
         },
         {
            name: 'CAT-5 Cable 100ft',
            price: '$' + 29.99,
            description: 'CAT-5 Cable 100ft',
            retailer: 'TechWorld',
            productImage: 'cablespool'
          },
          {
            name: 'Multimeter',
            price: '$' + 29.99,
            description: 'Multimeter',
            retailer: 'Ace Hardware',
            productImage: 'multimeter'
          },
          {
            name: 'Soldering Iron',
            price: '$' + 59.99,
            description: 'Soldering Iron',
            retailer: 'Home Depot',
            productImage: 'solderingiron'
          },
          {
            name: 'Multitool',
            price: '$' + 49.99,
            description: 'Multitool',
            retailer: 'Ace Hardware',
            productImage: 'multitool'
          },
          {
            name: 'Multimeter',
            price: '$' + 29.99,
            description: 'Multimeter',
            retailer: 'TechWorld',
            productImage: 'multimeter'
          },
          {
            name: 'Copper Wire(100ft)',
            price: '$' + 29.99,
            description: 'Copper Wire(100ft)',
            retailer: 'Radio Shack',
            productImage: '100ftwirespool'
          },
          {
            name: 'Computer Mouse',
            price: '$' + 43.99,
            description: 'Computer Mouse',
            retailer: 'Memory Express',
            productImage: 'pcmouse'
        },
      ],
      }
    },
    computed: {
      numberOfPages () {
        return Math.ceil(this.items.length / this.itemsPerPage)
      },
      filteredKeys () {
        return this.keys.filter(key => key !== 'Name')
      },
    },
    methods: {
      nextPage () {
        if (this.page + 1 <= this.numberOfPages) this.page += 1
      },
      formerPage () {
        if (this.page - 1 >= 1) this.page -= 1
      },
      updateItemsPerPage (number) {
        this.itemsPerPage = number
      },
    },
  }
</script>

<style scoped>
.productCard{
    text-align: center;
    vertical-align: middle;
    max-height: 400px
}
.img-cont{
  margin-left: auto;
  margin-right: auto;
}
</style>

I have a dynamically populated data iterator in Vuetify. Each item displays some information about a product as well as an image. The information is hidden until the card is expanded. Each card contains a switch that is meant to expand just that card. But each switch expands all cards at once. I have not been able to determine a solution. The Vuetify API documentation has not been much help.

StoreDisplay.vue:

<template>
  <v-container fluid>
    <v-data-iterator
      :items="items"
      :items-per-page.sync="itemsPerPage"
      :page.sync="page"
      :search="search"
      :sort-by="sortBy.toLowerCase()"
      :sort-desc="sortDesc"
      hide-default-footer
    >
      <template v-slot:header>
        <v-toolbar
          dark
          color="blue darken-3"
          class="mb-1"
        >
          <v-text-field
            v-model="search"
            clearable
            flat
            solo-inverted
            hide-details
            prepend-inner-icon="mdi-magnify"
            label="Search"
          ></v-text-field>
          <template v-if="$vuetify.breakpoint.mdAndUp">
            <v-spacer></v-spacer>
            <v-select
              v-model="sortBy"
              flat
              solo-inverted
              hide-details
              :items="keys"
              prepend-inner-icon="mdi-magnify"
              label="Sort by"
            ></v-select>
            <v-spacer></v-spacer>
            <v-btn-toggle
              v-model="sortDesc"
              mandatory
            >
              <v-btn
                large
                depressed
                color="blue"
                :value="false"
              >
                <v-icon>mdi-arrow-up</v-icon>
              </v-btn>
              <v-btn
                large
                depressed
                color="blue"
                :value="true"
              >
                <v-icon>mdi-arrow-down</v-icon>
              </v-btn>
            </v-btn-toggle>
          </template>
        </v-toolbar>
      </template>

      <template v-slot:default="{ items, isExpanded, expand }">
        <v-row>
          <v-col
            v-for="item in items"
            :key="item.name"
            cols="12"
            sm="6"
            md="4"
            lg="3"
          >
            <v-card>
              <v-container class="productCard" style="text-align:center" >
                <div class="img-cont" >
                <v-img
                  contain
                  :src="require('@/assets/'+ item.productImage +'.jpg')" alt="loading..."
                  max-height="200px"
                  />
              </div>
                <v-card-title class="subheading font-weight-bold">
                  <v-row >
                    <v-col>
                      <h4>{{item.name}}</h4>
                  </v-col>
                  </v-row>
                </v-card-title>
                <v-row>
                  <v-col>
                    <h4>{{item.price}}</h4>
                  </v-col>
                </v-row>
              </v-container>
              <v-switch
                :input-value="isExpanded(item)"
                :label="isExpanded(item) ? 'Expanded' : 'Closed'"
                class="pl-4 mt-0"
                @change="(v) => expand(item, v)"
              ></v-switch>
              <v-divider></v-divider>

              <v-list
                v-if="isExpanded(item)"
                dense
              >
                <v-list-item>
                  <v-list-item-content>Description:</v-list-item-content>
                  <v-list-item-content class="align-end">
                    {{ item.description }}
                  </v-list-item-content>
                </v-list-item>
                <v-list-item>
                  <v-list-item-content>Retailer:</v-list-item-content>
                  <v-list-item-content class="align-end">
                    {{item.retailer}}
                  </v-list-item-content>
                </v-list-item>
              </v-list>
            </v-card>
          </v-col>
        </v-row>
      </template>

      <template v-slot:footer>
        <v-row
          class="mt-2"
          align="center"
          justify="center"
        >
          <span class="grey--text">Items per page</span>
          <v-menu offset-y>
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                dark
                text
                color="primary"
                class="ml-2"
                v-bind="attrs"
                v-on="on"
              >
                {{ itemsPerPage }}
                <v-icon>mdi-chevron-down</v-icon>
              </v-btn>
            </template>
            <v-list>
              <v-list-item
                v-for="(number, index) in itemsPerPageArray"
                :key="index"
                @click="updateItemsPerPage(number)"
              >
                <v-list-item-title>{{ number }}</v-list-item-title>
              </v-list-item>
            </v-list>
          </v-menu>

          <v-spacer></v-spacer>

          <span
            class="mr-4
            grey--text"
          >
            Page {{ page }} of {{ numberOfPages }}
          </span>
          <v-btn
            fab
            dark
            color="blue darken-3"
            class="mr-1"
            @click="formerPage"
          >
            <v-icon>mdi-chevron-left</v-icon>
          </v-btn>
          <v-btn
            fab
            dark
            color="blue darken-3"
            class="ml-1"
            @click="nextPage"
          >
            <v-icon>mdi-chevron-right</v-icon>
          </v-btn>
        </v-row>
      </template>
    </v-data-iterator>
  </v-container>
</template>

<script>
  export default {
    data () { 
      return {
        itemsPerPageArray: [4, 8, 12],
        search: '',
        filter: {},
        sortDesc: false,
        page: 1,
        itemsPerPage: 4,
        sortBy: 'name',
        keys: [
          'Name',
          'Price',
          'Description',
          'Retailer'
        ],
        items: [
          {
            name: '6 foot HDMI cable',
            price: '
 + 19.99,
            description: '6 foot HDMI cable',
            retailer: 'Jones Audio/Visual',
            productImage: 'hdmicable'
          },
          {
            name: '23 inch Monitor',
            price: '
 + 199.99,
            description: '23 inch Monitor',
            retailer: 'Samsung',
            productImage: 'monitor'
          },
          {
            name: 'RJ45 Connectors (Pack of 30)',
            price: '
 + 14.99,
            description: 'CAT-5 Connectors (Pack of 30)',
            retailer: 'Electronics Emporium',
            productImage: 'RJ45Connector'
         },
         {
            name: 'CAT-5 Cable 100ft',
            price: '
 + 29.99,
            description: 'CAT-5 Cable 100ft',
            retailer: 'TechWorld',
            productImage: 'cablespool'
          },
          {
            name: 'Multimeter',
            price: '
 + 29.99,
            description: 'Multimeter',
            retailer: 'Ace Hardware',
            productImage: 'multimeter'
          },
          {
            name: 'Soldering Iron',
            price: '
 + 59.99,
            description: 'Soldering Iron',
            retailer: 'Home Depot',
            productImage: 'solderingiron'
          },
          {
            name: 'Multitool',
            price: '
 + 49.99,
            description: 'Multitool',
            retailer: 'Ace Hardware',
            productImage: 'multitool'
          },
          {
            name: 'Multimeter',
            price: '
 + 29.99,
            description: 'Multimeter',
            retailer: 'TechWorld',
            productImage: 'multimeter'
          },
          {
            name: 'Copper Wire(100ft)',
            price: '
 + 29.99,
            description: 'Copper Wire(100ft)',
            retailer: 'Radio Shack',
            productImage: '100ftwirespool'
          },
          {
            name: 'Computer Mouse',
            price: '
 + 43.99,
            description: 'Computer Mouse',
            retailer: 'Memory Express',
            productImage: 'pcmouse'
        },
      ],
      }
    },
    computed: {
      numberOfPages () {
        return Math.ceil(this.items.length / this.itemsPerPage)
      },
      filteredKeys () {
        return this.keys.filter(key => key !== 'Name')
      },
    },
    methods: {
      nextPage () {
        if (this.page + 1 <= this.numberOfPages) this.page += 1
      },
      formerPage () {
        if (this.page - 1 >= 1) this.page -= 1
      },
      updateItemsPerPage (number) {
        this.itemsPerPage = number
      },
    },
  }
</script>

<style scoped>
.productCard{
    text-align: center;
    vertical-align: middle;
    max-height: 400px
}
.img-cont{
  margin-left: auto;
  margin-right: auto;
}
</style>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

假扮的天使 2025-01-17 18:39:35

您可以尝试对 items 数据使用布尔值,并使用 v-if 来检查 item[index] 是否为 true,并考虑使用索引作为键,如下所示:

v-for="(item, itemIndex) in items" :key="itemIndex"

You can try using a boolean to your items data and use the v-if to check if the item[index] is true, and consider using an index as your key like so:

v-for="(item, itemIndex) in items" :key="itemIndex"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文