如何使 pinia 与 vue3 中的嵌套对象一起使用

如何获得更新嵌套属性的反应组件:

我有一个定义如下的 pinia 商店

import { defineStore } from "pinia"
export const useStore = defineStore({
    id: "poc",
    state: () => ({ str: "", nested: { obj: "" } }),
    persist: {
        enabled: true,
        strategies: [{ storage: localStorage }],
    },
})

和下面的 vue3 组件

<script lang="ts">
import { ref } from "vue"
import { storeToRefs } from "pinia"
import { useStore } from "./store"
export default {
    setup() {
        const store = useStore()
        const example = storeToRefs(store)

        const mStr = ref(example.str)
        const mObj = ref(example.nested.value.obj) // <--- this is where I believe the problem is
        store.str = mStr.value
        store.nested.obj = mObj.value

        return { mObj, mStr, store }
    },
}
</script>

<template>
    <h1>PoC</h1>
    <input v-model="mObj" placeholder="obj" />
    <input v-model="mStr" placeholder="str" />
</template>

当我更新 str 字段时,它按预期工作,但对于嵌套对象却没有。我怀疑我在调用 nested.value 时失去了反应性,也就是说 - 我不知道如何使它成为反应性。

stack overflow How to make a pinia work with nested objects in vue3
原文答案
author avatar

接受的答案

多一点挖掘, https://github.com/vuejs/pinia/discussions/854 终于给了我足够的力量,让我自己想出一个(更优雅的)解决方案。

<script lang="ts">
import { useStore } from "./store"
export default {
    setup() {
        const store = useStore()
        return { store }
    },
}
</script>

<template>
    <h1>test</h1>
    <input v-model="store.str" placeholder="obj" />
    <input v-model="store.nested.obj" placeholder="str" />
</template>

答案:

作者头像

FOR PINIA:解构状态结帐: storeToRefs ()

为了从存储中提取属性同时保持其反应性,您需要使用 storeToRefs()。它将为每个反应属性创建参考。当您仅使用商店中的状态但不调用任何操作时,这很有用。请注意,您可以直接从商店中解构操作,因为它们也绑定到商店本身

<script>
import { useStore } from "./store"
import { storeToRefs } from 'pinia' // NOTE this

export default {
    setup() {
        const store = useStore()
const {str, nested } = storeToRefs(store)
        return { str, nested }
    },
}
</script>

<template>
    <h1>test</h1>
    <input v-model="str" placeholder="obj" />
    <input v-model="nested.obj" placeholder="str" />
</template>