【问题标题】:Vue, how to handle reactivity with deeply nested objectsVue,如何处理深度嵌套对象的反应性
【发布时间】:2021-09-03 12:05:33
【问题描述】:

我有一个我正在操作的对象,如下所示:

const posts = [
    { key1: "abc", key2: [{ innerKey1: "def", innerKey2: 123 }, { innerKey1: "def", innerKey2: 123 }] },
    { key1: "abc", key2: [{ innerKey1: "def", innerKey2: 123 }, { innerKey1: "def", innerKey2: 123 }] },
    { key1: "abc", key2: [{ innerKey1: "def", innerKey2: 123 }, { innerKey1: "def", innerKey2: 123 }] },
];

posts[0].key2[1].innerKey1 = "newVal";

key2 中的 Array 是一个 prop,内部键预计会发生变化。我想在innerKey1 或innerKey2 更改时保持反应。

因为 Vue 难以检测数组和对象的变化,正如 here 所讨论的那样,我们不能直接通过索引修改数组或通过键修改对象。

为了保持反应性,我们似乎需要一些复杂的逻辑,使用Vue.set() 来设置newVal:

我的想法是:

Vue.set(posts, 1, Vue.set(key2, 0, Vue.set(innerKey1, "newVal")))

这是在这里保持反应性的最佳方式,还是我缺少一些可以使这更容易的东西?

注意: 我还尝试在我的子组件中使用深度观察器来观察key2 数组中发生的变化。但它似乎无法观察到这些变化。

//ChildComponent.vue
<html>
  <div>
   <RandomComponent v-for="thing in key2" :key... :innerKey2="thing.innerKey2">
  </div>
</html>

<script>
props: {
    key2: {
        type: Array,
        require: true,
    },
},
watch: {
    key2: {
        immediate: true,
        deep: true,
        handler () {
            console.log("Watcher working"); //Does not fire when parent mutates innerKeys
        },
    },
},
</script>

【问题讨论】:

  • 按索引修改数组在这里是一个错误,这不会触发反应。见vuejs.org/v2/guide/reactivity.html#For-Arrays
  • 是的,这就是我在帖子中所说的。这就是为什么我建议用Vue.set(posts, 1, Vue.set(key2, 0, Vue.set(innerKey1, "newVal"))) 替换它并链接同一页面的原因。我再澄清一下,我好像不太清楚
  • 就是这样,或者使用数组方法替换一个元素,即用splice.
  • 有时我们也会看到这样的东西:this.array = [...this.array, newItem] 或this.array = this.array.filter(etc)
  • 做同样的技术,但是从更高的地方开始。 this.outerData = complexFuncToGetNewOuterData(this.outerData)

标签: javascript vue.js vue-reactivity


【解决方案1】:

我觉得这个问题不够清晰。

  • 如果您只想更新现有数组元素的属性,按索引进行变异应该可以正常工作,无需任何解决方法。

即这应该是反应式的

posts[0].key2[1].innerKey1 = "newVal";
  • 但是,如果您尝试 替换 数组 element 您需要解决 Vue 反应性问题的解决方法 here

我认为最适合您的情况的解决方法是使用 Array.splice 替换元素。 (例如网络响应后)

  const postId = 0 // the root element 
  const updatePost = { ...this.posts[postId] }
  updatePost.key2[1].innerKey1 = 'newVal'

  this.posts.splice(postId, 1, updatedPost);

这是我在codesanbox制作的插图

【讨论】:

    猜你喜欢
    • 2021-10-02
    • 2017-08-04
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多