ウェブサイト検索

typescript - PrimeVueで親コンポーネントから子コンポーネントにスロットを渡す方法は?


私はいくつかの PrimeVue コンポーネントをラップして、自分のコンポーネントライブラリを作ろうとしています。しかし、すべてのスロットはどのように扱えばよいのでしょうか?

一部の PrimeVue コンポーネントには多くのスロットがあるため、それぞれを個別に渡すのは非常に面倒です。

幸いなことに、親コンポーネントから子コンポーネントにすべてのスロットを渡すこの解決策を見つけました。

こちらは PrimeVue ドロップダウンコンポーネントでの使用例です:

<Dropdown v-bind="$attrs" >
  <template v-for="(_, name) in $slots" #[name]="scope">
    <slot :name v-bind="scope" />
  </template>
</Dropdown>

残念ながら、PrimeVueでは動作しません。TypeScriptがDropdownSlotsにインデックスシグネチャがないことに関して、#[name]でこのエラーを出すためです:

要素は暗黙的に 'any' 型を持っています。なぜなら、'string | number' 型の式は 'DropdownSlots' 型のインデックスとして使用できないからです。

型 'DropdownSlots' には、型 'string' のパラメータを持つインデックス署名が見つかりませんでした。ts(7053)

何か回避策のアイデアはありますか?

回答 #1

TypeScriptのエラーが出ているからといって、コードが間違っているわけではありません。Vueのテンプレートは設計上現在型安全ではなく、型チェックにはサードパーティのツール(vue-tsc、IDEなど)が必要であり、それらには独自の癖がある場合があります。

子供やプロップスをテンプレートではなくレンダリング関数で変換する方が簡単です。これにより、テンプレートで型を使用することに関連する問題も回避できます。シンプルなラッパーコンポーネントの場合は次の通りです。

setup(props, { slots }) {
  return () => h(Dropdown, props, slots);
}

回答 #2

これらのスロット転送に関連するすべての問題を解決するために、Vue Forward Slotsという素晴らしいパッケージを見つけました: https://www.npmjs.com/package/vue-forward-slots

デフォルトスロットを含むすべてのスロットを転送するために、このように使っています:

  <ForwardSlots :exclude="[]">
    <Dropdown v-bind="$attrs" />
  </ForwardSlots>

いつかこのようなものが core vue.js に取り入れられることを願っています。