【问题标题】:Vuex mutation error when pass Object (with objects) to component将对象(带有对象)传递给组件时出现Vuex突变错误
【发布时间】:2017-01-08 00:07:58
【问题描述】:

描述(tl;dr):

当我通过 v-model 将“对象的对象”从 vuex 的存储区传递给组件时,模型的修改会产生错误。 在“Object of Objects”通过时。对于任何其他类型,一切正常。

当我说“对象的对象”时,我指的是这个结构:{'A': {name: 'first'}, 'B': {name: 'second'}}

工作流程和结构

  • 结构:view (page) -> parent -> child;
  • View 从 store 中获取 Object 并将其传递给组件 (->parrent->child);
  • 不允许使用“.sync”,因此组件不应改变存储中的对象;
  • child 修改后,child 必须返回结果到parentparentviewview 应该通过 vuex 的 setter 保存;

错误信息

Error when evaluating setter "value.name": Error: [vuex] Do not mutate vuex store state outside mutation handlers. (found in component: <child>)

Getter(来自商店)

getObjFromStore // return {'A': {name: 'first'}, 'B': {name: 'second'}}

查看(页面)

<parent :value="getObjFromStore"></parent>

父组件

<template>
  <div v-for="v in value">
    <child :value="v"></child>
  </div>
</template>

<script>
  import Child from 'components/child'

  export default {
    data () {
      return {}
    },
    props: {
      value: {
        type: Object
      }
    },
    components: {
      Child
    }
  }
</script>

子组件

<template>
  <input type="text" v-model="value.name">
</template>

<script>
  export default {
    data () {
      return {}
    },
    props: {
      value: {
        type: Object
      }
    }
  }
</script>

P.S. 我认为问题的发生是因为对象通过引用传递。但是如何解决这个错误呢?

【问题讨论】:

    标签: javascript vue.js vue-component vuex


    【解决方案1】:

    查看Vuex form handling 文档。它鼓励使用 @input 事件或 v-model 与计算道具...

    假设 obj 是一个计算属性,它从存储中返回一个 Object,这里的 v-model 将尝试在用户输入输入时直接改变 obj.message。在严格模式下,这将导致错误,因为突变不是在显式的 Vuex 突变处理程序中执行的。

    【讨论】:

    • 我已经知道了,但是@input 不适合我的情况,我无法在我的组件中定义自定义 getter/setter,因为我必须使用事件并在顶部使用 setter(查看)。我想了解为什么只有当里面有对象的对象已经通过时才会发生这个错误
    • 好吧,如果你从存储中获取一个对象,它只能通过突变来修改,而不是通过对象上的直接设置器(v-model 使用这些设置器)。我有点困惑...您是否想在一个应用程序中混合搭配 Vuex 和 vanilla Vue 方法?
    • 是的,因为低级组件不应该知道关于商店的任何事情。基本上是userView -> userList -> list。比List 应该直接向userList 提供数据(更改),而不是存储。而userList 可以包含一些其他元素(按钮)并且应该直接向userView 提供数据。 View 有自己的商店并将自己的状态保存到其中。我的工作流程很糟糕吗?
    • 其背后的想法是允许userList 与任何其他页面一起工作(每个页面都有自己的商店)。而list也可以是userListcarList等的通用部分。
    • 所以问题是较低的组件(list)应该传递单向绑定数据。但是数据是双向绑定的
    【解决方案2】:

    基本上只有2个选项:

    1. 将对象的深拷贝传递给props
    2. @input 事件或v-model 与计算道具一起使用(如pkawiak 的回答https://stackoverflow.com/a/39249362/930170);

    我更喜欢使用 deepcopy,但我确信对象不会太大。这种方法有助于保持代码更干净,更易于维护。

    第二种方法仅适用于预期对象非常大的情况

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-09
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      • 2018-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多