Heim  >  Fragen und Antworten  >  Hauptteil

Probleme mit Vue.js 3 und Pinia Getters

Ich wechsle von Angular zu Vue.js und versuche, seine Architektur zu verstehen. Ich stecke derzeit bei einem grundlegenden Problem fest und habe viele Problemumgehungen angewendet, aber ich suche eigentlich nur nach vorübergehenden Lösungen.

Das Hauptproblem hierbei ist die Zusammenarbeit zwischen Vue.js 3 und Pinia. Pinia besteht aus Store, Getter und Action. Manchmal haben wir sehr verschachtelte Objekte im Store und wir benötigen nur bestimmte Teile davon. Hierfür wäre es perfekt, einen Getter zu erstellen, um beispielsweise nur den Teil des Objekts auszugeben, den ich benötige.

Aber was ist, wenn ich genau diese Teile des Objekts aus der Vorlage ändern möchte? Mein Wunsch ist, dass sich auch die Daten im Shop ändern. Da Getter jedoch schreibgeschützt sind, ist dies nicht möglich.

Wie geht es hier weiter?

Natürlich möchte ich dir ein Beispiel zeigen, um meine Erklärung mit etwas Übung zu untermauern.

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: {}
})

Ich verwende hier ein sehr verschachteltes Objekt roles 创建一个商店。在我在 v-for 模板中使用的 getter getElementsForCurrentRole, bei dem ich nur bestimmte Elemente benötige.

Um das Verständnis für alle zu erleichtern, werde ich den Vorlagencode auch hier veröffentlichen:

<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>

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

Ich verstehe das nicht, ich kann es nicht verstehen.

Um dieses Problem zu umgehen, berechne ich derzeit den alten und neuen Index des Datensatzes im Array nach dem Ziehen basierend auf dem Ereignis und aktualisiere den Speicher manuell. Aber das konnte nicht der Zweck dahinter sein. Verstehe ich etwas in der Architektur grundsätzlich falsch? Wie würden Menschen mit einer solchen Situation umgehen?

P粉668019339P粉668019339350 Tage vor648

Antworte allen(1)Ich werde antworten

  • P粉034571623

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

    您正在使用吸气剂。 Getter 是只读属性。要更新任何 pinia 商店中的值,您必须创建一个操作。 并且您正在使用 v-model,它会在值更改时进行绑定和写入。因此,它可以使用 getter 读取,但不能写入。对于你的情况有几种可能性。其中之一是创建计算属性和操作。像这样

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

    以及组件中的计算属性:

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

    Antwort
    0
  • StornierenAntwort