【问题标题】:How to collect selected BootstrapVue (b-form-checkbox) check boxes?如何收集选中的 BootstrapVue (b-form-checkbox) 复选框?
【发布时间】: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') &times;
                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') &times;
</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') &times;
                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') &times;
</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
    })
  },
}

对“表单复选框输入”的引用:

https://bootstrap-vue.org/docs/components/form-checkbox

【问题讨论】:

    标签: vue.js nuxt.js bootstrap-vue


    【解决方案1】:

    我建议您仔细考虑您的代码,并准备好逻辑步骤:

    1. 您根据 Vuex 商店中的列表列出了 UI 项列表
    2. 每个 UI 项都有一个切换(复选框),用于设置它所显示的项的部分状态(是否应该删除)
    3. 通过单击切换(复选框),项目的状态应该会改变
    4. 通过点击按钮(删除),Vuex 的状态应该会改变:删除状态满足条件的每一个项目(它是toRemove,状态是true

    就是这样。更简单地说:不要通过选择一些 UI 元素来工作。通过更新 UI 元素所基于的数据状态来工作。 (让 Vue 的反应能力来完成剩下的工作。)

    第一个 sn-p 很简单,不使用 Vuex

    Vue.component('RowWithCb', {
      props: ["id", "title", "checked"],
      computed: {
        isChecked: {
          get() {
            return this.checked
          },
          set(val) {
            this.$emit("update:checked", val)
          }
        },
      },
      template: `
        <b-row>
          <b-col
            class="d-flex"
          >
            <div>
              <b-checkbox
                v-model="isChecked"
              />
            </div>
            <div>
              {{ title }}
            </div>
          </b-col>
        </b-row>
      `
    })
    new Vue({
      el: "#app",
      computed: {
        toRemove() {
          return this.rows.filter(({
            checked
          }) => checked)
        },
        toKeep() {
          return this.rows.filter(({
            checked
          }) => !checked)
        },
      },
      data() {
        return {
          rows: [{
              id: 1,
              title: "Row 1",
              checked: false,
            },
            {
              id: 2,
              title: "Row 2",
              checked: false,
            }
          ]
        }
      },
      template: `
        <b-container>
          <b-row>
            <b-col>
              <h3>Items:</h3>
              <row-with-cb
                v-for="row in rows"
                :key="row.id"
                v-bind="{
                 ...row
                }"
                :checked.sync="row.checked"
              />
            </b-col>
          </b-row>
          <hr />
          <b-row>
            <b-col>
              <h4>To keep:</h4>
              {{ toKeep }}
            </b-col>
            <b-col>
              <h4>To remove:</h4>
              {{ toRemove }}
            </b-col>
          </b-row>
        </b-container>
      `
    })
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <div id="app"></div>

    现在使用 Vuex

    const initialState = () => ({
      rows: [{
          id: 1,
          title: "Row 1",
          checked: false,
        },
        {
          id: 2,
          title: "Row 2",
          checked: false,
        }
      ]
    })
    
    const store = new Vuex.Store({
      state: initialState(),
      mutations: {
        RESET(state) {
          const init = initialState()
          for (key in init) {
            state[key] = init[key]
          }
        },
        SET_TO_REMOVE(state, {
          id,
          checked
        }) {
          state.rows = state.rows.map(row => {
            if (row.id === id) {
              return {
                ...row,
                checked,
              }
            } else {
              return row
            }
          })
        },
        REMOVE_SELECTED(state) {
          state.rows = state.rows.filter(({
            checked
          }) => !checked)
        },
      },
      actions: {
        reset({
          commit
        }) {
          commit("RESET")
        },
        setToRemove({
          commit
        }, data) {
          commit("SET_TO_REMOVE", data)
        },
        removeSelected({
          commit
        }) {
          commit("REMOVE_SELECTED")
        },
      },
      getters: {
        getRows: state => state.rows,
        getRowsToRemove: state => state.rows.filter(({
          checked
        }) => checked),
        getRowsToKeep: state => state.rows.filter(({
          checked
        }) => !checked),
      }
    })
    
    Vue.component('RowWithCb', {
      props: ["id", "title", "checked"],
      computed: {
        isChecked: {
          get() {
            return this.checked
          },
          set(val) {
            this.$emit("update:checked", {
              id: this.id,
              checked: val,
            })
          }
        },
      },
      template: `
        <b-row>
          <b-col
            class="d-flex"
          >
            <div>
              <b-checkbox
                v-model="isChecked"
              />
            </div>
            <div>
              {{ title }}
            </div>
          </b-col>
        </b-row>
      `
    })
    new Vue({
      el: "#app",
      store,
      computed: {
        rows() {
          return this.$store.getters.getRows
        },
        toRemove() {
          return this.$store.getters.getRowsToRemove
        },
        toKeep() {
          return this.$store.getters.getRowsToKeep
        },
      },
      methods: {
        handleSetChecked(data) {
          this.$store.dispatch("setToRemove", data)
        },
        handleRemoveItems() {
          this.$store.dispatch("removeSelected")
        },
        handleResetStore() {
          this.$store.dispatch("reset")
        },
      },
      template: `
        <b-container>
          <b-row>
            <b-col>
              <h3>Items:</h3>
              <row-with-cb
                v-for="row in rows"
                :key="row.id"
                v-bind="{
                 ...row
                }"
                v-on="{
                  'update:checked': (data) => handleSetChecked(data)
                }"
              />
            </b-col>
          </b-row>
          <hr />
          <b-row>
            <b-col>
              <h4>To keep:</h4>
              {{ toKeep }}
            </b-col>
            <b-col>
              <h4>To remove:</h4>
              {{ toRemove }}
            </b-col>
          </b-row>
          <hr />
          <b-row>
            <b-col>
              <b-button
                @click="handleRemoveItems"
              >
                REMOVE
              </b-button>
              <b-button
                @click="handleResetStore"
              >
                RESET
              </b-button>
            </b-col>
          </b-row>
        </b-container>
      `
    })
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <script src="https://unpkg.com/vuex"></script>
    <div id="app"></div>

    您可以看到我没有弄乱任何复选框或 UI 元素(唯一的区别是 id 也是从 UI 组件发出的)。所有功能都移至Vuex 商店,仅此而已。 (比第一个 sn-p 更详细一点,因为我添加了删除和重置功能。)


    让我们分解一下

    1。您需要一个列出项目的组件。在这种情况下,让我们为此使用根组件:

    new Vue({
      el: "#app",
      data() {
        return {
          baseItems: [{
              id: "item_1",
              name: "Item 1",
            },
            {
              id: "item_2",
              name: "Item 2",
            },
          ]
        }
      },
      computed: {
        items() {
          return this.baseItems
        },
      },
      template: `
        <ul>
          <li
            v-for="item in items"
            :key="item.id"
          >
            {{ item.name }}
          </li>
        </ul>
      `
    })
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <div id="app"></div>

    我故意将items 设置为computed - 切换到Vuex 会很容易。

    2。你知道你列出的项目会比这更复杂一些,所以让我们创建一个component 来处理它们即将到来的复杂性:

    Vue.component('ListItem', {
      props: ['id', 'name'],
      template: `
        <li>
          {{ name }}
        </li>
      `
    })
    
    new Vue({
      el: "#app",
      data() {
        return {
          baseItems: [{
              id: "item_1",
              name: "Item 1",
            },
            {
              id: "item_2",
              name: "Item 2",
            },
          ]
        }
      },
      computed: {
        items() {
          return this.baseItems
        },
      },
      template: `
        <ul>
          <list-item
            v-for="item in items"
            :key="item.id"
            v-bind="{
              ...item,
            }"
          />
        </ul>
      `
    })
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <div id="app"></div>

    3。让我们让它们可拆卸 - 一个接一个或一组:

    Vue.component('ListItem', {
      props: ['id', 'name', 'toRemove'],
      computed: {
        selected: {
          get() {
            return this.toRemove
          },
          set(val) {
            this.$emit('update:to-remove', val)
          }
        },
      },
      template: `
        <li>
          <input
            type="checkbox"
            v-model="selected"
          />
          {{ name }}
        </li>
      `
    })
    
    new Vue({
      el: "#app",
      data() {
        return {
          baseItems: [{
              id: "item_1",
              name: "Item 1",
              toRemove: false,
            },
            {
              id: "item_2",
              name: "Item 2",
              toRemove: false,
            },
          ]
        }
      },
      computed: {
        items() {
          return this.baseItems
        },
      },
      methods: {
        handleRemoveSelected() {
          this.baseItems = this.baseItems.filter(item => !item.toRemove)
        },
      },
      template: `
        <div>
          So, it's easier to follow:
          {{ items }}
          <hr />
          <ul>
            <list-item
              v-for="item in items"
              :key="item.id"
              v-bind="{
                ...item,
              }"
              :toRemove.sync="item.toRemove"
            />
          </ul>
          <b-button
            @click="handleRemoveSelected"
          >
            REMOVE SELECTED
          </b-button>
        </div>
      `
    })
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <div id="app"></div>

    好的,现在有了你想要的功能 - 没有Vuex

    4。让我们混入Vuex

    • 将列表移至Vuex 状态
    • 将选择移至Vuex 操作
    • 将删除移至Vuex 操作

    // initial state is a function per Vuex best practices
    const initialState = () => ({
      items: [{
          id: "item_1",
          name: "Item 1",
          toRemove: false,
        },
        {
          id: "item_2",
          name: "Item 2",
          toRemove: false,
        }
      ]
    })
    
    const store = new Vuex.Store({
      state: initialState(),
      mutations: {
        // so you are able to reset the store to
        // initial state
        RESET(state) {
          const init = initialState()
          for (key in init) {
            state[key] = init[key]
          }
        },
        // this handles the "checked" state if each item
        SET_TO_REMOVE(state, {
          id,
          toRemove,
        }) {
          // returning a new, modified array
          // per FLUX process
          state.items = state.items.map(item => {
            if (item.id === id) {
              return {
                ...item,
                toRemove,
              }
            } else {
              return item
            }
          })
        },
        // the same function that was in the app before
        REMOVE_SELECTED(state) {
          state.items = state.items.filter(({
            toRemove
          }) => !toRemove)
        },
      },
      actions: {
        reset({
          commit
        }) {
          commit("RESET")
        },
        // action to commit the mutation: select item for removal
        setToRemove({
          commit
        }, data) {
          commit("SET_TO_REMOVE", data)
        },
        // action to commit the mutation: remove items
        removeSelected({
          commit
        }) {
          commit("REMOVE_SELECTED")
        },
      },
      getters: {
        getItems: state => state.items,
      }
    })
    
    Vue.component('ListItem', {
      props: ['id', 'name', 'toRemove'],
      computed: {
        selected: {
          get() {
            return this.toRemove
          },
          set(val) {
            this.$emit('update:to-remove', val)
          }
        },
      },
      template: `
        <li>
          <input
            type="checkbox"
            v-model="selected"
          />
          {{ name }}
        </li>
      `
    })
    
    new Vue({
      el: "#app",
      store,
      data() {
        return {
          baseItems: [{
              id: "item_1",
              name: "Item 1",
              toRemove: false,
            },
            {
              id: "item_2",
              name: "Item 2",
              toRemove: false,
            },
          ]
        }
      },
      computed: {
        items() {
          return this.$store.getters.getItems
        },
      },
      methods: {
        handleSetToRemove(data) {
          // data should be: { id, toRemove }
          this.$store.dispatch("setToRemove", data)
        },
        handleRemoveSelected() {
          this.$store.dispatch("removeSelected")
        },
        handleResetStore() {
          this.$store.dispatch("reset")
        },
      },
      template: `
        <div>
          So, it's easier to follow:
          {{ items }}
          <hr />
          <ul>
            <list-item
              v-for="item in items"
              :key="item.id"
              v-bind="{
                ...item,
              }"
              @update:to-remove="(toRemove) => handleSetToRemove({
                id: item.id,
                toRemove,
              })"
            />
          </ul>
          <b-button
            @click="handleRemoveSelected"
          >
            REMOVE SELECTED
          </b-button>
          <b-button
            @click="handleResetStore"
          >
            RESET
          </b-button>
        </div>
      `
    })
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
    <script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
    <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <script src="https://unpkg.com/vuex"></script>
    <div id="app"></div>

    这就是它的全部内容。

    1. 您在小组件中处理选择 - 但选定状态的更改在此组件内不是 HANDLED,而是发送给父级,而父级又通过调用 Vuex 操作来处理此问题。这会改变 Vuex 商店中的状态,并通过道具“流”回。

    2. 如果您单击REMOVE SELECTED,则不会查看组件(如果它们被选中),而是调用另一个Vuex 操作,从@987654350 的状态中删除所有选定的项目(通过过滤) @ 店铺。由于所有项目都从 Vuex 存储的 getter 中取出(如果底层状态发生变化,getter 会更新),新状态出现在列表中。

    因此,在这种情况下,使用Vuex 可能看起来有点矫枉过正,但如果您计划为列出的项目设置更复杂的状态,那么它可能是合理的。

    【讨论】:

    • 我尝试将您的方法应用于 Vuex,但它不起作用。最有可能我做错了什么。请查看原帖中的更新部分。
    • @tesicg 我知道已经一周了,但我希望我仍然可以提供帮助。
    猜你喜欢
    • 2020-03-30
    • 2020-03-09
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2021-11-10
    • 2016-04-25
    • 1970-01-01
    相关资源
    最近更新 更多