(Vuetify) Switch 扩展了数据迭代器的所有元素,而不仅仅是一个
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以尝试对
items
数据使用布尔值,并使用v-if
来检查item[index]
是否为 true,并考虑使用索引作为键,如下所示:You can try using a boolean to your
items
data and use thev-if
to check if theitem[index]
is true, and consider using an index as your key like so: