【问题标题】:How to properly deal with editable complex object (nested) with vuex?如何使用 vuex 正确处理可编辑的复杂对象(嵌套)?
【发布时间】:2019-01-11 08:07:10
【问题描述】:

Vuex 非常适合显示复杂的数据,并进行复杂的突变(比如向树中添加一个节点,影响整个商店等),但是,对我来说,处理“复杂对象上的简单”突变。

我面临的一个用例(非常)简单:我有一个显示列表对象(具有嵌套属性和数组)的组件。每个属性都是可编辑的。每个对象都显示有一个子组件。 (我需要在叶子属性上使用 v-model)

另一个用例是使用组件方法打开的模式对话框,允许编辑对象的一些属性/嵌套属性(而且,我需要在叶属性上使用 v-model)

目前,这就是我所做的: 在显示/编辑对象的组件中,我在组件的data 中放入了可以编辑的对象的“骨架”(具有所有嵌套属性的对象,但所有叶子都设置为null)。然后,当模式打开,或者组件应该显示/使对象可编辑时,我只需将对象(使用递归函数)深度复制到 data 之一,然后使用 deep 选项观看数据到 @ 987654325@,并提交每次更改。

这感觉有点不对劲,需要付出相当大的努力才能让它发挥作用。

我喜欢突变可追溯系统,我希望每次对嵌套属性进行修改时提交我的整个对象。如果可以不编写这么多代码,那将是非常棒的(我想知道是否不值得简单地放弃 vuex 以获得一个简单的全局 Vue 组件存储......并权衡好的突变系统对于简单的代码)

那么是否有“标准”方式或“推荐方式”......或者只是一种“智能”方式来做到这一点而不需要这样的努力?

商店状态示例:

state = {
  foo : [
    bar : {
      users : [
        {
          name : '',
          adddr : '',
          needs : ['a', 'b', 'c'],
          baz : [
            {
              k1 : v1,
              k2 : v2,
              k3 : [1,2,3,4,5],
            },
            //...
          ]
        },
        //...
      ]
    }
  ]
}

...而且我想每次都提交整个用户。

【问题讨论】:

  • 您能否发布一些您的 Vuex 实例的示例?

标签: vuejs2 vuex


【解决方案1】:

嗯...这个问题让我非常恼火,以至于我编写了一个模块来处理所有这些复杂的情况。可以在这里找到它:https://github.com/hl037/vue-data-proxy

然后,我们可以简单地编写这种组件:

import vueDataProxy from "vue-data-proxy";

export default {
  props : {
    user_ind;
  }
  computed : {
    ...vueDataProxy({
      user : {
        fetch() {
          return this.$store.state.foo.bar.users[this.user_ind];
        },
        commit(val){
          // here, val is the full object (if reactivity injected)
          // returned by fetch
          this.$store.commit('updateUser', {ind : this.user_ind, val}
        }
     }
  },
  //...
}

...假设你有一个名为updateUser(state, {ind, val}) { /*...*/ }的突变

...然后,它将在任何深度上提交每个修改

【讨论】:

  • 这很有趣!我的问题是我的状态对象没有深度嵌套,而是包含一堆bar[]foo[],其中每个barfoo 也是对象。每个数组将包含 0 个或多个元素。我发现根据用户在 UI 上添加/删除数据的交互,在每个数组中添加和删除元素非常麻烦。这里有什么提示吗?
  • 我认为将 vuex 与 vueJS 3 一起使用实际上对于几乎所有用例来说都有些矫枉过正......在我看来,使用组合 api 的 setup() 和每个子状态似乎更容易和更简单你会在你的 vuex 存储中,创建一个 js/ts 全局和反应对象作为存储在一个专用文件中,添加一个全局 getter 函数来返回这个对象。然后无论如何都需要这个文件/吸气剂。这样,什么组件使用什么存储等就很清楚了。如果您需要跟踪突变,只需通过返回自定义 getter 来记录访问...
  • 我在 Vue2 中使用 vuex。听说过 vue3 composition api,但不是很了解。我怀疑我们是否会迁移到 vue3,因为它的风险太大。
【解决方案2】:

我建议这样使用:

  1. 组件包含要更新的属性的完整路径(这将被触发)
  2. 在 vuex 中使用 lodash 或其他类似工具使用完整路径设置属性。

组件

<template>
        <input v-on:change="update(‘object.nested.more.nested.attribute’, $event)" v-text:value="object.nested.mote.nested.attribute"></span>
</template>


<script>
 export default  {
  methods: {
    update: function (property, value) {
      this.$store.dispatch(UPDATE_COMPLEX_OBJECT, {property, value})
    }
  }
}
</script>

VUEX

import _ from 'lodash'

export default {
  namespaced: true,
  state: {
   myObject: {}
  },
  mutations: {
    [UPDATE_COMPLEX_OBJECT] (state, data) {
      _.set(state.myObject, data.property, data.value)
    }
  },
  actions: {
    [UPDATE_COMPLEX_OBJECT]: ({commit}, data) => {
      commit(UPDATE_COMPLEX_OBJECT, data)
    }
  }

}

如果有什么不清楚的地方请告诉我,希望对您有所帮助。 谢谢!

【讨论】:

  • 我认为它会更新,但是你如何将值绑定到输入呢? (无论如何,我认为它比我目前的解决方案更“hacky”)
  • 您好,您需要创建一个简单的组件,这需要是较小的可能表示形式,例如叶子。检查 Vuetifyjs,它有一个可扩展的列表,可能会对您有所帮助。 vuetifyjs.com/en/components/lists。检查扩展列表
【解决方案3】:

假设您有一个复杂的嵌套对象,如下所示:

{
  super: {
    nested: {
      object: {
        to: {
          be: {
            updated: 'foo'
          }
        }
      }
    }
  }
}

现在,您可能想要更新特定键的操作:

import * as types        from '../mutation-types'
import * as defaultStore from '../defaultStore'

export default {

  namespaced: true,

  state: defaultStore.complexObject,

  getters: {
    getSettings: state => state
  },

  mutations: {
    [types.UPDATE_SUPER_NESTED_OBJECT] (state, payload) {
      state.super.nested.object.to.be.updated = payload
    }
  },

  actions: {
    updateSuperNestedObject (store, payload) {
      return store.commit(types.UPDATE_SUPER_NESTED_OBJECT, payload)
    }
  }

}

在您的组件中:

import { mapActions } from 'vuex'

export default {

 computed: {
   ...mapActions('<modulename>', ['updateSuperNestedObject'])
 }

 methods: {
   handleUpdate(payload) {
     return this.updateSuperNestedObject('bar')
   }
 }

}

希望对你有帮助!

【讨论】:

  • 不,您只针对叶子。我想提交一个完整的“子树”来保持反应性(但我添加了一个示例来说明它,并且(如果它是随机数据)“复杂”足以证明我不能为每个键进行突变
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 2023-03-16
  • 1970-01-01
  • 2018-11-19
  • 2021-05-22
  • 1970-01-01
  • 2019-12-05
  • 2015-07-23
相关资源
最近更新 更多