Vue.js のコンポーネントを名前付きでエクスポートしたい
状況
以下のような App.vue と ChildComponent があるとする。
<script setup lang="ts">
import ChildComponent from './components/ChildComponent.vue';
</script>
<template>
<h1>App.vue</h1>
<ChildComponent></ChildComponent>
</template>
<script setup lang="ts">
</script>
<template>
<h2>ChildComponent.vue</h2>
</template>
App.vue で ChildComponent と、ファイル名と同名でインポートしている。
しかし FooBar など、ファイル名と全く異なる名前でインポートしても特に問題ない。
のだが、
- 毎回ファイル名をコピペするのが面倒
- 別名でインポートされる可能性があるのもなんかヤダ
- VS Code でのインポートの追加が効かず、自分で
import文を書かねばならない
などが気になっていた。
検討案
なんとか解決できんかな、と以下を検証してみた。
-
index.tsを作成してインポート/エクスポート -
<script>タグにて自分自身をインポート/エクスポート
index.ts を作成してインポート/エクスポート
コンポーネントと同一ディレクトリ、もしくは親ディレクトリなどに index.ts を作成し、以下のように記載する。
import ChildComponent from './ChildComponent.vue';
export { ChildComponent };
もしくは省略して以下のように。
export { default as ChildComponent } from './ChildComponent.vue';
App.vue の <template> で <Foo と入力しているタイミングでインポート候補が表示されるようになる。

1 つ目の ./components から import した場合は 以下のように。
<script setup lang="ts">
import { ChildComponent } from './components';
</script>
<template>
<h1>App.vue</h1>
<ChildComponent></ChildComponent>
</template>
この場合、インポート名は index.ts で指定した名称のみが指定可能となる。
次に 2 つ目の ./components/ChildComponent.vue から import した場合は 以下のように。
<script setup lang="ts">
import ChildComponent from './components/ChildComponent.vue';
</script>
<template>
<h1>App.vue</h1>
<ChildComponent></ChildComponent>
</template>
./components/ChildComponent.vue からの import 文は元々と同じだが、インポートの追加が楽にはなるし、インポートする名前も自動的に設定される。ただしインポート名を自由に変更されてしまう可能性は残る。
<script> タグにて自分自身をインポート/エクスポート
<script> タグを利用して自分自身でエクスポートしてみる。
ChildComponent.vue を以下のように変更する。
<script>
export { default as ChildComponent } from './ChildComponent.vue';
</script>
<script setup lang="ts">
</script>
<template>
<h2>ChildComponent.vue</h2>
</template>
<script setup> では export ができないが、併用可能な <script> にて export は可能なので、 <script> タグ内に記述する。
上記から一部引用
<script setup>は、通常の<script>と一緒に使うことができます。次のことが必要な場合は、通常の<script>が必要になることがあります:
inheritAttrsや、プラグインで有効になるカスタムオプションなど、<script setup>では表現できないオプションを宣言する(3.3+ ではdefineOptionsで置き換え可能)- 名前付きのエクスポートを宣言する
- 副作用を実行したり、一度しか実行してはいけないオブジェクトを作成する
この 2 つ目に該当、、、するのだろうか、、、。まあともかく動作はする。
App.vue は以下のようになる。
<script setup lang="ts">
import { ChildComponent } from './components/ChildComponent.vue';
</script>
<template>
<h1>App.vue</h1>
<ChildComponent></ChildComponent>
</template>
ただしこちらの場合も default export からの import は引き続き可能ではある。
まとめ
- どちらの場合も
default exportからのimportを行う可能性は残る- しかし VS Code のインポートの追加が機能するだけでもメリットはあると感じる
-
<script>でのexportについて、循環参照的な状況にならないのか-
npm run dev,npm run buildともに問題ない様子ではある
-
別ファイルを作成する必要もない <script> タグでのエクスポートが良いのではないか、と思うのだけど、ざっと検索してみたものの特に事例が見当たらないし、私自身の Vue.js や JS/TS の知見も浅いのでこれでいいのかなー、という疑問は残る。どうなんだろ。
Discussion