在Vuex

时间:2019-07-01 19:53:22

标签: vuejs2 vuex

我正在尝试将用户输入从表单绑定到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})
    }
  }
}

但是显然这是行不通的,因为我无法将索引传递给计算属性。 有人对此有解决方案吗?这对于深入的观察者来说是一个很好的用例吗?

这是我的第一个问题,如果我忘记了某件事或做错了什么,请让我知道,以便改进我的提问。谢谢!

1 个答案:

答案 0 :(得分:0)

当数据不稳定时,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内部商店状态的“规则”。