Maison  >  Questions et réponses  >  le corps du texte

Problèmes avec Vue.js 3 et Pinia Getters

Je passe d'Angular à Vue.js et j'essaie de comprendre son architecture. Je suis actuellement confronté à un problème fondamental et j'ai utilisé de nombreuses solutions de contournement, mais je ne cherche en réalité que des solutions temporaires.

Le principal problème ici est la collaboration entre Vue.js 3 et Pinia. Pinia comprend Store, Getter et Action. Parfois, nous avons des objets très imbriqués dans le Store et nous n’en avons besoin que de certaines parties. Créer un getter serait parfait pour cela, par exemple, pour afficher uniquement la partie de l'objet dont j'ai besoin.

Mais que se passe-t-il si je souhaite modifier exactement ces parties de l'objet à partir du modèle ? Mon souhait est que les données du magasin changent également. Mais comme les getters sont en lecture seule, cela n'est pas possible.

Comment procéder ici ?

Bien sûr, je veux vous montrer un exemple pour souligner mon explication avec un peu de pratique.

export const useGeneralStore = defineStore('general', {
  state: () => {
    return {
      roles: [],
      currentRole: 'basic',
    }
  },
  getters: {
    getElementsForCurrentRole: (state) => {
      let role = state.roles.find((role) => {
        return role.value == state.currentRole;
      });

      if (role) {
        return role.data;
      }
    }
  },
  actions: {}
})

J'utilise ici un objet très imbriqué roles 创建一个商店。在我在 v-for 模板中使用的 getter getElementsForCurrentRole où je n'ai besoin que de certains éléments.

Afin de faciliter la compréhension de chacun, je publierai également le code du modèle ici :

<template>
  <div class="element-container">
    <div v-for="cat of elementCategories" :key="cat">
      <h4>{{cat}}</h4>
      <draggable 
        v-model="getElementsForCurrentRole" 
        :group="cat"
        @end="save" 
        item-key="name">
        <template #item="{element}">
          <n-card v-if="element.category == cat" class="element" :class="element.name" :title="element.name" size="small" header-style="{titleFontSizeSmall: 8px}" hoverable>
            <n-switch v-model:value="element.active" @update:value="save(element)" size="small" />
          </n-card>
        </template>
      </draggable>
    </div>
  </div>
</template>

<script setup>
  import { NCard, NSwitch, useMessage } from 'naive-ui';
  import draggable from 'vuedraggable'
  import { usePermissionsStore } from '@/stores/permissions';
  import { storeToRefs } from 'pinia';

  const permissionsStore = usePermissionsStore();
  const { getElementsForCurrentRole } = storeToRefs(permissionsStore);  

  const elementCategories = ['basic', 'professional'];
</script>

Utilisez storeToRefs 函数后,我循环遍历 getElementsForCurrentRole getter,以使数据具有反应性。我的问题是数据可能只是部分反应性的。例如,如果我更改 Switch 元素的值,则商店更新成功。这有效。但是,我似乎无法访问正在循环的数组的顺序。一旦我通过拖放更改顺序,我就会收到消息:写入操作失败:计算值是只读 comme mentionné dans la documentation.

Je ne comprends pas ça, je ne peux pas le comprendre.

Pour contourner le problème, je calcule actuellement l'ancien et le nouvel index de l'enregistrement dans le tableau après avoir fait glisser en fonction de l'événement et mets à jour le stockage manuellement. Mais cela ne pouvait pas être le but recherché. Est-ce que j'ai fondamentalement mal compris quelque chose dans l'architecture ? Comment les gens géreraient-ils une telle situation ?

P粉668019339P粉668019339350 Il y a quelques jours646

répondre à tous(1)je répondrai

  • P粉034571623

    P粉0345716232023-11-04 15:30:00

    Vous utilisez un getter. Getter est une propriété en lecture seule. Pour mettre à jour la valeur dans n'importe quel magasin Pinia, vous devez créer une action. Et vous utilisez un modèle v qui se lie et écrit lorsque la valeur change. Par conséquent, il peut être lu à l’aide de getters, mais pas écrit. Il existe plusieurs possibilités selon votre situation. L'un d'eux consiste à créer des propriétés et des opérations calculées. Comme ça

    actions: {
      updateRole(newRole) {
        this.currentRole = newRole
    }

    Et propriétés calculées dans les composants :

    const myComputed = computed({
      get: () => getElementsForCurrentRole.value,
      set: (val) => updateRole(val),
    })

    répondre
    0
  • Annulerrépondre