Vererbung/gemeinsame Operationen und Getter in Pinia
P粉662614213
P粉662614213 2023-12-22 13:50:12
0
2
465

Ich habe mehrere Pinia-Stores, die sich eine Reihe von Operationen und Gettern teilen sollen, bin mir aber nicht ganz sicher, wie ich das effizient erreichen kann.

Ich baue eine Anwendung, mit der Benutzer viele verschiedene Medien (Bücher, Filme, Fernsehsendungen usw.) verwalten können. Ich denke derzeit darüber nach, für jeden Medientyp einen Shop einzurichten, etwa BookStore, MovieStore usw. Viele Getter und Operationen (z. B. countdeleteOne) sind zwischen diesen verschiedenen Geschäften genau gleich.

Wie implementiert man hier DRY? Die Beispiele in der Pinia-Dokumentation konzentrieren sich auf die Wiederverwendung von Aktionen und Gettern in anderen Stores, aber ich glaube nicht, dass dies meinen Anwendungsfall der direkten Vererbung einer Reihe von Gettern und Settern vollständig abdeckt.

Ist der Vererbungsansatz, den ich hier versuche, ein Anti-Pattern?

P粉662614213
P粉662614213

Antworte allen(2)
P粉420958692

如果您想让某些功能在并非所有商店之间共享,您可以使用可组合方式。

您可以创建一个单独的可组合函数并将商店实例的一部分传递给其中。

我在 codesandbox 上做了一个例子为你。

这里是codesandbox的简短示例:

common.ts

import { computed, Ref, ref } from "vue";

export function useCommon(initValue: number) {
    const _value = ref<number>(initValue);

    function increment() {
        _value.value++;
    }

    function someProcessing() {
        // ... some code here
    }

    return {
        counter,

        increment,
        someProcessing,
    };
}

然后在任何商店中您都可以像这样使用它:

fooStore.ts

export const useFooStore = defineStore('foo', () => {
    const state = ref<string>('foo');

    const { counter, increment, someProcessing } = useCounter(0);

    return {
        state,

        counter,
        increment,
        someProcessing,
    }
}

通过这种方式,您可以在任何存储或任何组件中组合任何函数、对象等。

P粉449281068

这可以使用插件来实现 docs

示例电影:

您有多个商店,每个州都使用共享命名方案:

  • 项目:单个实体项目(单个电影详细信息)
  • collection:项目集合(所有电影的集合)

每个商店都会有相同的 CRUD 操作,只是 URL 发生变化

创建插件:

function BaseStorePlugin () {
    return {
        collection: [],
        item: {},
        getCollection: function (url) {
            api.get(url)
                .then((response) => {
                    this.collection = response.data;
                })
                .catch((error) => {
                    this.handleError(error);
                });
        },
        getItem: function (url) {
            api.get(url)
                .then((response) => {
                    this.item = response.data;
                })
                .catch((error) => {
                    this.handleError(error);
                });
        },
        handleError: function (error) {
            window.alert(error);
        },
    };
}

给 Pinia 提供插件:

const pinia = createPinia();

pinia.use(BaseStorePlugin);

示例 movieStore.js(使用共享操作和状态)

import { defineStore } from 'pinia';
import { api } from 'src/boot/axios';

export const useMovieStore = defineStore({
    id: 'movie',
    state: () => ({
        movieSpecificStateObject: {},
    }),
    actions: {
        movieSpecificAction (url) {
            console.log(this.item);
            api.get(url)
                .then((response) => {
                    // handle response
                })
                .catch((error) => {
                    this.handleError(error);
                });
        },
    },
});

组件中的使用示例

<template>
    <div
        v-for="movie in movieStore.collection"
        :key="movie.id"
    >
        <div>
            {{ movie.name }}
        </div>
    </div>
</template>

<script setup>
import { onMounted } from 'vue';
import { useMovieStore } from 'src/stores/movieStore.js';
const movieStore = useMovieStore();

onMounted(() => {
    movieStore.readCollection('http://url.com/movies');
});
</script>

编辑:1

如果您将上下文传递到插件中,您就可以访问商店和传递到其中的选项,从中您可以检查商店 ID,并且仅返回特定商店,如下所示

function BaseStorePlugin (context) {
  const allowedStores = ['movie', 'album'];

  if (allowedStores.includes(context.store.$id)) {
    return {
      collection: [],
      getCollection: function () {
        const fakeCollection = Array.from({length: 10}, () => Math.floor(Math.random() * 40));
        fakeCollection.forEach((item) => {
          this.collection.push({
            id: item,
            name: `name${item}`
          });
        });
      },
    };
  };
}

我使用 3 个商店创建了一个非常基本的示例,上面的检查可在 codesandbox 此处

Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!