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