搜索

首页  >  问答  >  正文

使用 Vue3 和 TypeScript 将 Pinia Store 作为 Prop 传递

<p>我正在使用 Typescript、Pinia 和 Vue3,并且有一个 <code>MenuButton</code> 组件,我希望能够传递用于菜单打开状态以及要显示的操作的 Pinia 存储/隐藏。应用程序中有几个不同的菜单,因此我希望能够将它们传入,并且它们都使用相同的工厂来定义商店。我正在尝试弄清楚如何让所有这些都与打字稿一起使用。</p> <pre class="lang-js prettyprint-override"><code>// nav.store.ts import { defineStore } from "pinia"; import { useStorage } from "@vueuse/core"; import type { RemovableRef } from "@vueuse/core"; export interface MenuStore { isOpen: RemovableRef<boolean>, toggle(force?: boolean) : void, open(): void, close(): void, } interface State { isOpen: RemovableRef<boolean>; } function menuStoreFactory(id: string) { return defineStore(id, { state: () : State => ({ isOpen: useStorage(`${id}-open`, false), }), actions: { toggle(force?: boolean) { this.isOpen = force != undefined ? force : !this.isOpen; }, open() { this.isOpen = true; }, close() { this.isOpen = false; } } }); } export const useMainMenuStore = menuStoreFactory('mainMenu'); export const useMobileMenuStore = menuStoreFactory('mobileMenu'); </code></pre> <pre class="lang-js prettyprint-override"><code>// setup script for the menu button component import { MenuIcon, MenuLeftIcon } from "@/icons"; import type { MenuStore } from "@/modules/nav/nav.store"; interface Props { controller: MenuStore } const props = defineProps<Props>(); </code></pre> <p>那么用法就非常简单了:</p> <pre class="lang-html prettyprint-override"><code><template> <MenuButton :controller="mainMenu" ></MenuButton> </template> <script setup lang=ts"> const mainMenu = useMainMenuStore(); </script> </code></pre> <p>在当前界面中,我收到了道具不匹配的错误。经过一番研究,我将界面变成了以下内容,修复了使用错误,但随后在 <code>MenuButton</code> 组件中引发了 <code>toggle()</code> 和 <code>isOpen< 的错误/code> 尚未解决。</p>
导出接口 MenuStore 扩展 PiniaCustomStateProperties<{
    isOpen: RemovableRef,
    切换(力?:布尔值):无效,
    打开():无效,
    关闭():无效,
}> {}
</代码></pre>
<p>另一个接近的尝试调整是:</p>
<pre class="lang-js Prettyprint-override"><code>导出接口 MenuStore 扩展 Store,
    切换(力?:布尔值):无效,
    打开():无效,
    关闭():无效,
}> {}
</代码></pre>
<p>这导致使用时出现此错误,但中组件没有错误</p>
类型 _StoreWithState & UnwrapRef<状态> & _StoreWithGetters<{}> & {toggle(force?: boolean): void, close(): void, open(): void} & PiniaCustomProperties & PiniaCustomStateProperties<状态>不可分配给类型 MenuStore ...   类型 PiniaCustomStateProperties;不可分配给类型 MenuStore

P粉899950720P粉899950720486 天前697

全部回复(1)我来回复

  • P粉187677012

    P粉1876770122023-08-26 14:00:15

    您的问题似乎主要是关于您需要的类型/接口,所以我会回答这个问题。

    您可以简单地使用返回的存储的类型,而不是自己编写类型。

    您有一个工厂函数,它返回 defineStore 的返回值,它本身就是一个返回存储的函数。因此,可以使用 typeof 获取工厂函数的类型,然后使用 TypeScript 的 ReturnType 帮助器深入了解返回类型,从而找到存储的类型。

    以下应该是您所需要的:

    export type MenuStore = ReturnType<ReturnType<typeof menuStoreFactory>>
    

    细分:

    ReturnType<                 // C
      ReturnType<               // B
        typeof menuStoreFactory // A
      >
    >
    
    • A:获取工厂函数的类型。
    • B:获取工厂函数的返回类型,即defineStore的返回值。这本身就是一个返回存储的函数。
    • C: 获取该函数的返回类型。这是商店本身的类型。

    回复
    0
  • 取消回复