【问题标题】:Use v-bind on array of objects in Vuex在 Vuex 中的对象数组上使用 v-bind
【发布时间】:2019-11-12 11:10:47
【问题描述】:

我正在尝试将表单中的用户输入绑定到我的 vuex 商店中的状态。

状态如下:

customers: [
  {firstName: "", lastName: "", age: ""},
  {firstName: "", lastName: "", age: ""},
  {firstName: "", lastName: "", age: ""}
]

我尝试在调用 get 和 set 方法的计算属性上使用 v-model。我找到了解释here。

这对一个对象非常有效,但不幸的是没有解释如何在对象数组上使用它。

我正在寻找这样的东西:

computed: {
  firstName: {
    get () {
      return this.$store.state.customers[i].firstName
    },
    set (value) {
      this.$store.commit('changeFirstname', {value, index})
    }
  }
}

但显然这不起作用,因为我无法将索引传递给计算属性。 有没有人解决这个问题?对于深度观察者来说,这是一个很好的用例吗?

这是我的第一个问题,如果我忘记了什么或做错了什么,请告诉我,以便我改进我的提问。谢谢!

【问题讨论】:

标签: vuejs2 vuex


【解决方案1】:

当您的数据不平坦时,Vuex 可能会有点麻烦。有关更多信息,请参阅https://forum.vuejs.org/t/vuex-best-practices-for-complex-objects/10143。

解决此问题的一种方法是放弃 v-model 并直接使用 :value 和 @input。我在示例中模拟了一家商店,但希望很清楚发生了什么。如果您发现这比传递对象本身更容易,那么您可以轻松获取客户的索引。

const storeCustomers = Vue.observable([
  {firstName: "A", lastName: "", age: ""},
  {firstName: "B", lastName: "", age: ""},
  {firstName: "C", lastName: "", age: ""}
])

function storeGetCustomers () {
  return storeCustomers
}

function storeUpdateCustomerFirstName (customer, value) {
  customer.firstName = value
}

new Vue({
  el: '#app',
  
  computed: {
    customers () {
      return storeGetCustomers()
    }
  },
  
  methods: {
    onFirstNameInput (customer, value) {
      storeUpdateCustomerFirstName(customer, value)
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <div v-for="customer in customers">
    <input :value="customer.firstName" @input="onFirstNameInput(customer, $event.target.value)">
  </div>
  <p>
    {{ customers }}
  </p>
</div>

保留v-model 的替代方法是引入一个单独的组件来容纳每个客户。一般来说,当使用v-for 进行任何涉及编辑的事情时,值得考虑引入一个新组件。

在此示例中存在不对称性,即从父级存储中读取客户并写入子级存储中。我觉得这有点不舒服。也许如果每个客户都有一个 id,那么该 id 可以作为道具而不是客户对象传递给孩子,让孩子获取和设置它感兴趣的单个客户。

const storeCustomers = Vue.observable([
  {firstName: "A", lastName: "", age: ""},
  {firstName: "B", lastName: "", age: ""},
  {firstName: "C", lastName: "", age: ""}
])

function storeGetCustomers () {
  return storeCustomers
}

function storeUpdateCustomerFirstName (customer, value) {
  customer.firstName = value
}

const child = {
  props: ['customer'],
  
  template: `
    <div>
      <input v-model="firstName">
    </div>
  `,
  
  computed: {
    firstName: {
      get () {
        return this.customer.firstName
      },
      
      set (value) {
        storeUpdateCustomerFirstName(this.customer, value)
      }
    }
  }
}

new Vue({
  el: '#app',
  
  components: {
    child
  },
  
  computed: {
    customers () {
      return storeGetCustomers()
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <child v-for="customer in customers" :customer="customer"></child>
  <p>
    {{ customers }}
  </p>
</div>

关于你关于深度观察者的问题,我相信你所描述的将涉及改变商店外的状态,然后让观察者让商店知道它。商店实际上不会做任何事情,因为状态已经改变了。显然,这将违反关于仅在商店的mutations 内改变商店状态的“规则”。

【讨论】:

  • 感谢@skirtle 的精彩解释!我感谢您的时间和精力。我遵循了您的第二个建议,并且效果很好。
  • 这是一些天才代码。这对我帮助很大。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 2018-08-26
  • 2018-07-12
  • 1970-01-01
  • 2018-10-02
  • 2020-08-08
  • 2023-01-21
相关资源
最近更新 更多