Dan*_*ter 6 inheritance vue.js pinia
我有几个 Pinia 商店应该共享一组操作和 getter,但我不太确定如何有效地实现这一点。
\nI\xe2\x80\x99m 构建一个应用程序,让用户管理多种不同的媒体(书籍、电影、电视节目等)。我\xe2\x80\x99m 目前考虑的方式是为每种媒体类型创建一个存储,例如 BookStore、MovieStore 等。这些不同存储之间的许多 getter 和操作(例如count和deleteOne)完全相同。
我如何在这里实现 DRY?Pinia文档中的示例主要集中在其他商店内重用操作和 getter,但我不\xe2\x80\x99t 认为这完全解决了我直接继承一组 getter 和 setter 的用例。
\n我在这里尝试的继承方法是反模式吗?
\nThis is achievable using plugins docs
Example Movies:
You have multiple stores using shared naming scheme for each state:
each store will have the same CRUD actions with only the URL changing
创建插件:
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);
},
};
}
Run Code Online (Sandbox Code Playgroud)
给 Pinia 提供插件:
const pinia = createPinia();
pinia.use(BaseStorePlugin);
Run Code Online (Sandbox Code Playgroud)
示例 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);
});
},
},
});
Run Code Online (Sandbox Code Playgroud)
组件中的用法示例
<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>
Run Code Online (Sandbox Code Playgroud)
编辑: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}`
});
});
},
};
};
}
Run Code Online (Sandbox Code Playgroud)
我使用 3 个商店创建了一个非常基本的示例,上面的检查可在 codeandbox 上找到