【发布时间】:2021-06-11 23:55:48
【问题描述】:
我在 Nuxt.js (Vue.js) 应用程序上工作,模态对话框如下所示:
Basket.vue 组件代码如下:
<template lang="pug">
b-container(v-if='products.length > 0')
b-row
b-col(:cols="8")
b-container
b-row
b-list-group
b-list-group-item.flex-column.align-items-start(v-for="(product, index) in products" :key="index")
b-container
b-row
b-col(:cols="1").d-flex.align-items-center.justify-content-center
b-form-checkbox {{ index + 1 }}
b-col(:cols="11")
basket-item(:product="product")
b-row.row-middle-style
b-button.close(type='button' aria-label='Close' @click="onRemoveItem")
span(aria-hidden='true') ×
u Remove selected items
b-button(type='button' @click="onContinue()").btn.btn-lg.buy__button Продолжить покупки
b-row
div
hr
| * доставка будет осуществлена из Санкт-Петербурга;
br
| * наш менеджер свяжется с вами сразу после обработки заказа;
...
</template>
<script lang="ts">
import Vue from 'vue'
import BasketItem from './BasketItem.vue'
import { mapState, mapActions } from 'vuex'
export default Vue.extend({
components: {
BasketItem,
},
data() {
return {
}
},
computed: {
...mapState(['products']),
},
methods: {
...mapActions({
onRemoveItem: 'removeItem',
}),
},
})
</script>
<style lang="sass">
...
</style>
BasketItem.vue 组件代码如下:
<template lang="pug">
b-container
b-row.style-item-row
b-col(:cols="3")
img(:src="product.image" :alt="product.alt")
b-col(:cols="4")
div {{ product.name }}
div {{ product.description }}
b-col(:cols="4")
div Цена {{ product.price }}
div Количество {{ product.quantity }}
b-col(:cols="1")
b-button.close(type='button' aria-label='Close' @click="onRemoveItem(product.id)")
span(aria-hidden='true') ×
</template>
<script lang="ts">
import Vue from 'vue'
import { mapActions } from 'vuex'
export default Vue.extend({
props: {
product: {
type: Object,
},
},
data() {
return {
}
},
methods: {
...mapActions({
onRemoveItem: 'removeItem',
}),
},
})
</script>
<style lang="sass">
...
</style>
Vuex 代码如下:
import * as mutationTypes from './mutation_types'
export const state = () => ({
products: [
{
id: 1,
image: 'https://licota.ru/system/product_images/attachments/5d9b/1781/6332/3406/9d00/2a31/small/8bfa7c2c-c7c7-11e4-80f4-002590d99cf6.jpg?1570445184',
alt: 'Товар 1',
name: 'Товар 1',
description: 'Описание 1',
price: 100,
quantity: 4
},
{
id: 2,
image: 'https://licota.ru/system/product_images/attachments/5d9b/329f/6332/3406/9d00/9336/small/e6a69bba-3450-11e9-812c-002590d99cf6.jpg?1570452124',
alt: 'Товар 2',
name: 'Товар 2',
description: 'Описание 2',
price: 200,
quantity: 7
}
]
})
export const getters = {
}
export const actions = {
removeItem({ commit }, id) {
commit(mutationTypes.REMOVE_ITEM, id)
}
}
export const mutations = {
[mutationTypes.REMOVE_ITEM] (state, id) {
state.products = state.products.filter(x => {
return x.id != id
})
}
}
如您所见,我有一个项目列表(有两个)。在它们每个前面都是BootstrapVue (b-form-checkbox) 复选框。我可以选择其中任何一个,然后单击“删除所选项目”。之后,它们将被删除。该操作的代码目前不存在。可以看到的Vuex代码是指点击item右上角的“x”。
我的问题是如何收集选中的项目,即选中的复选框以删除适当的项目?
更新:
我已经尝试过您的建议,但它不起作用。最有可能我做错了什么。 实际上,当我查看 DevTools 中的 Vue 部分时,单击复选框后 isChecked 计算属性不会改变。代码如下所示:
Basket.vue:
<template lang="pug">
b-container(v-if='products.length > 0')
b-row
b-col(:cols="8")
b-container
b-row
b-list-group
b-list-group-item.flex-column.align-items-start(
v-for="(product, index) in products"
:key="product.id"
v-bind="{...product}"
v-on="{'update:checked': (data) => handleSetChecked(data)}"
)
b-container.set_pad
b-row
b-col(:cols="12").d-flex.align-items-center.justify-content-center
basket-item(:product="product" :productIndex="index")
b-row.row-middle-style
b-button.close(type='button' aria-label='Close' @click="onRemoveSelectedItems")
span(aria-hidden='true') ×
u Удалить выбранное
b-button(type='button' @click="onContinue()").btn.btn-lg.buy__button Продолжить покупки
b-row
div
hr
| * доставка будет осуществлена из Санкт-Петербурга;
br
| * наш менеджер свяжется с вами сразу после обработки заказа;
...
</template>
<script>
import Vue from 'vue'
import BasketItem from './BasketItem.vue'
import { mapActions } from 'vuex'
export default Vue.extend({
components: {
BasketItem,
},
data() {
return {}
},
computed: {
products() {
return this.$store.getters.getProducts
},
toRemove() {
return this.$store.getters.getProductsToRemove
},
},
methods: {
...mapActions({
onRemoveItem: 'removeItem',
}),
handleSetChecked(data) {
this.$store.dispatch("setToRemove", data)
},
handleRemoveItems() {
this.$store.dispatch("removeSelected")
},
onRemoveSelectedItems() {
this.handleRemoveItems()
},
},
})
</script>
BasketItem.vue:
<template lang="pug">
b-container
b-row.style-item-row
b-col(:cols="1").d-flex.align-items-center.justify-content-center
b-form-checkbox(v-model="isChecked") {{ productIndex + 1 }}
b-col(:cols="3")
img(:src="product.image" :alt="product.alt")
b-col(:cols="3")
div {{ product.title }}
div {{ product.description }}
b-col(:cols="4")
div Цена {{ product.price }}
div Количество {{ product.quantity }}
b-col(:cols="1")
b-button.close(type='button' aria-label='Close' @click="onRemoveItem(product.id)")
span(aria-hidden='true') ×
</template>
<script>
import Vue from 'vue'
import { mapActions } from 'vuex'
export default Vue.extend({
props: {
product: {
type: Object,
},
productIndex: {
type: Number,
},
},
data() {
return {}
},
computed: {
isChecked: {
get() {
return this.product.checked
},
set(val) {
this.$emit("update:checked", {
id: this.product.id,
checked: val,
})
}
},
},
methods: {
...mapActions({
onRemoveItem: 'removeItem',
}),
},
})
</script>
Vuex:
import * as mutationTypes from './mutation_types'
export const state = () => ({
products: [
{
id: 1,
image: 'https://licota.ru/system/product_images/attachments/5d9b/1781/6332/3406/9d00/2a31/small/8bfa7c2c-c7c7-11e4-80f4-002590d99cf6.jpg?1570445184',
alt: 'Товар 1',
title: 'Товар 1',
description: 'Описание 1',
price: 100,
quantity: 4,
checked: false
},
{
id: 2,
image: 'https://licota.ru/system/product_images/attachments/5d9b/329f/6332/3406/9d00/9336/small/e6a69bba-3450-11e9-812c-002590d99cf6.jpg?1570452124',
alt: 'Товар 2',
title: 'Товар 2',
description: 'Описание 2',
price: 200,
quantity: 7,
checked: false
}
]
})
export const getters = {
getProducts: state => state.products,
getProductsToRemove: state => state.products.filter(({
checked
}) => checked),
}
export const actions = {
setToRemove({
commit
}, data) {
commit("SET_TO_REMOVE", data)
},
removeSelected({
commit
}) {
commit("REMOVE_SELECTED")
},
removeItem({ commit }, id) {
commit(mutationTypes.REMOVE_ITEM, id)
},
}
export const mutations = {
SET_TO_REMOVE(state, {
id,
checked
}) {
state.products = state.products.map(product => {
if (product.id === id) {
return {
...product,
checked,
}
} else {
return product
}
})
},
REMOVE_SELECTED(state) {
state.products = state.products.filter(({
checked
}) => !checked)
},
[mutationTypes.REMOVE_ITEM] (state, id) {
state.products = state.products.filter(x => {
return x.id != id
})
},
}
对“表单复选框输入”的引用:
【问题讨论】:
标签: vue.js nuxt.js bootstrap-vue