Pinia 对象在 Vue 中的 foreach 后失去反应性

问题描述 投票:0回答:1

我有这个嵌套的 foreach BalanceItemList.vue

<template>
    <div v-for="category in categoryItemsStore.balanceCategories" :key="category.id" class="mt-5">
        <div class="border-black border-b bg-gray-200">
            <span class="font-bold w-full">{{ category.name }}</span>
        </div>

        <div v-for="balanceItem in category.balance_items" :key="balanceItem.id">
            {{ balanceItem.total = 500 }}
            <balance-item :balance-item="balanceItem" @update-balance-item="update"/>
        </div>
        <div>
            <balance-item-create :category="category.id" @create-balance-item="update"/>
        </div>
        <div v-if="categoryItemsStore.totals[category.id]" class="grid grid-cols-4-b t-2 ml-2">
            <div :class="category.is_positive ? '': 'text-red-600' "
                 class="col-start-4 border-t-2 border-black font-bold">
                &euro;{{ categoryItemsStore.totals[category.id].total }}
            </div>
        </div>
    </div>

</template>

我像这样检查了“balanceItem”的反应性

{{ balanceItem.total = 500 }}

它在商店中更新,但随后我有了我的平衡项目组件: BalanceItem.vue

<script setup>
import {reactive} from "vue";
import {useForm} from "@inertiajs/vue3";
import NumberInput from "@/Components/NumberInput.vue";
import {UseCategoryItemsStore} from "@/Stores/UseCategoryItemsStore.js";

const categoryItemStore = UseCategoryItemsStore()

const props = defineProps({balanceItem: Object, errors: Object})

let item = reactive(props.balanceItem);

const form = useForm(item);

const emit = defineEmits(['update-balance-item'])

const submit = () => {
    form.post(route('balance-item.update'), {
        preserveScroll: true,
        onSuccess: () => {
            props.balanceItem.total = 500
            categoryItemStore.updateBalanceItemsTotals(form)
            emit('update-balance-item')
        }
    })

}

</script>

<template>
    <form @submit.prevent="submit">
        <div class="grid grid-cols-4-b">
            <span>{{ item.name }}</span>
            <NumberInput
                v-model="form.count"
                autofocus
                class=" mr-4 mt-1 block"
                type="number"
                @update:model-value="submit"
            />
            <div :class="item.item_category.is_positive ? '' : 'text-red-600'" class="flex place-items-center">
                <div class="pt-1 mr-1">&euro;</div>
                <NumberInput
                    v-model="form.amount"
                    :class="form.errors.amount ? 'border-red-600' : ''"
                    autofocus
                    class="mt-1 mr-4 w-5/6"
                    type="text"
                    @update:model-value="submit"
                />
            </div>
            <div :class="item.item_category.is_positive ? '' : 'text-red-600'" class="flex place-items-center">
                <div class="pt-1 mr-1 w-5/6">&euro;</div>
                <NumberInput
                    v-model="form.total"
                    autofocus
                    class="mt-1 block"
                    disabled
                    style="max-width: 95%"
                    type="text"
                />
            </div>
        </div>
    </form>
</template>

这是我测试反应性的商店。如果我增加输入的数字,则项目的计数保持不变 UseCategoryItemsStore.js

import {defineStore} from "pinia";
import {ref} from "vue";

export const UseCategoryItemsStore = defineStore('UseCategoryItemsStore', () => {
    const balanceCategories = ref([])
    const totals = ref([])

    function getBalanceItems() {
        axios.get(route('balance-item.index')).then((response) => {
            balanceCategories.value = response.data
            // console.log(balanceCategories.value)
        })
    }

    function getTotals() {
        axios.get(route('balance-item.totals')).then((response) => totals.value = response.data)
    }

    function getData() {
        getTotals()
        getBalanceItems()
    }

    function updateBalanceItemsTotals(selectedItem) {
        balanceCategories.value.forEach((category) => {
            category.balance_items.forEach((item) => {
                if (item.id === selectedItem.id) {
                    // item.total = item.count * item.amount
                    console.log(item)
                }
            })
        })
    }

    getTotals()
    getBalanceItems()

    return {balanceCategories, totals, getBalanceItems, getTotals, getData, updateBalanceItemsTotals}
})

在此测试中,我执行“props.balanceItem.total = 500”。但如果我检查商店,它不会更新。看来将“balanceItem”分配给一个道具会失去与我的 Pinia 商店的反应性。我可以使用“form.total = form.count * form.amount”手动更新我的表单,但这对我来说似乎很老套,我想使用 Pinia 商店的反应性。我考虑过根据“BalanceItem”获取 Pina 项目,但这似乎也很棘手。谁知道为什么失去反应性?

我有laravel 10.39、vue3.2.41和pinia 2.1.17惯性0.6.11。到目前为止我知道的所有最新版本。

vue.js inertiajs pinia
1个回答
0
投票

我像这样更新我的表格和商店:

<script setup>
import {useForm} from "@inertiajs/vue3";
import NumberInput from "@/Components/NumberInput.vue";
import {UseCategoryItemsStore} from "@/Stores/UseCategoryItemsStore.js";

const categoryItemStore = UseCategoryItemsStore()
const props = defineProps({balanceItem: Object, errors: Object})

let item = categoryItemStore.getItemById(props.balanceItem);

let form = useForm(item);

const emit = defineEmits(['update-balance-item'])

const submit = () => {
    form.post(route('balance-item.update'), {
        preserveScroll: true,
        onSuccess: () => {
            item = categoryItemStore.updateItem(form)
            form = useForm(item)
            emit('update-balance-item')
        }
    })

}

</script>

我将此功能添加到我的商店:

import {defineStore} from "pinia";
import {ref} from "vue";

export const UseCategoryItemsStore = defineStore('UseCategoryItemsStore', () => {
    const balanceCategories = ref([])
    const totals = ref([])

    function getBalanceItems() {
        axios.get(route('balance-item.index')).then((response) => {
            balanceCategories.value = response.data
            // console.log(balanceCategories.value)
        })
    }

    function getItemById(item) {
        let category = balanceCategories.value.find((category) => {
            return category.id === item.item_category_id
        })

        return category.balance_items.find((item_from_store) => {
            return item_from_store.id === item.id
        })
    }

    function updateItem(form) {
        const item = getItemById(form)
        item.count = form.count
        item.amount = form.amount
        item.total = item.count * item.amount

        return item
    }

    function getTotals() {
        axios.get(route('balance-item.totals')).then((response) => totals.value = response.data)
    }

    function getData() {
        getTotals()
        getBalanceItems()
    }

    getTotals()
    getBalanceItems()

    return {balanceCategories, totals, getBalanceItems, getTotals, getData, getItemById, updateItem}
})

假设如果帖子获得 200,我的表单值可用于更新商店和更新表单。这是我能想到的最好的

© www.soinside.com 2019 - 2024. All rights reserved.