【Nuxt3】composablesがめっちゃ強いかもしれない

シェアする:

この記事をおすすめしたい人

  • Nuxt3でも名前空間なしでグローバル変数を使いたい人
  • Nuxt3のcomposablesをスルーした人
  • つまりオレ

Nuxt v3の調査、composables編です。

あまり分かってないんですが、Nuxtにはcomposablesという機能があるようです。 v3の新機能じゃなくてv2にもあったらしい。

思ってたよりどうも柔軟に使えるみたいで、v3で使えなくなった機能の代用になりそうな可能性があるので、挙動を見ていきます。

composablesってなんやねん

意味は「構成可能な」でわけわかりません。

例として挙がっているuseAppConfigとかを見ていると、script内などでまずこんな↓感じで呼び出して、


const config = useAppConfig()

それをtemplateやscriptでこんな↓風に使う。


<template>
<h1>{{config.title}}</h1>
</template>

<scipt setup lang="ts">
const config = useAppConfig()

useHead({
  title: config.title,
})
</script>

特定の処理の変数や関数をまとめて定義して、それをいろんなとこで使い回す、みたいなコンセプトに見えます。 クラスみたいな?

デフォルトで用意されているものがあり、公式のこのページの左メニューのcomposablesに一覧があります。

この記事のメインはそっちではなくて、自作のcomposablesの方です。

プロジェクトルートに「composables」フォルダを作ると、自前でcomposablesを定義できるみたいなんです。 自動インポートに対応しているので特にnuxt.configに書かなくても大丈夫。

こいつの挙動を見ていきます。

意外と簡単に呼び出せる

上のuse系で使ったことのあるやつは全部?オブジェクトが返ってくるので、ある程度の規模があるものと思っていたのですが、実際に触ってみるともっと小規模で簡単に呼び出す形でも書けるようでした。

公式の「Method 1: Using named export」を参考に書いてみます。


export function composablesTest() {
  return 'composables-test'
}

オブジェクトだけでなく、こんな風に関数や変数単体での書き方が可能です。

コイツの呼び出し方は、まずはuseAppConfigとかと同じようにこんな↓やり方。


export default defineNuxtComponent({
  mounted() {
    const test = composablesTest()
    
    console.log(test)
  },
})

これで「composables-test」が出力されます。

さらにですね、template内に


{{composablesTest()}}

と書いても同じ内容がHTMLに出力されるんですよ。

Nuxt側が用意しているものが規模が大きいから「そういうもの」と思い込んでいましたが、こんな感じのコンパクトな運用も可能みたい。

変数としても出力できる

上の書き方だと関数なので後ろに()つけないといけなかったんですが、こんな↓風に書くとカッコいりませんでした。


export const composablesTestConst = 'composables-test-const'

これだとtemplate内でこんな↓風に書けるのでかなり使いやすそう。


{{composablesTestConst}}

もうちょっと複雑な処理を含めて、なおかつ変数的に扱いたい場合はこの↓ようにcomputedを使えばカッコなしで使えます。


export const composablesTestComputed = computed(() => {
  return 'composables-test-computed'
})

これができるとなると、v2でVue.mixinでやっていたグローバル変数なんかの代わりにできそうです。 v2ではscriptからのアクセスはthisが必要だったのが、composablesだとthisが不要になりますが、機能的には同じことができそう。

ひとつのファイルに複数定義できる

export defaultが1ファイルに1個(1個だよね?)だからこれも1個と思い込んでいましたが、上の書き方だと複数の変数や関数を定義できるみたいです。


export function composablesTestFunction() {
  return 'composables-test-function'
}

export const composablesTestConst = 'composables-test-const'

export const composablesTestComputed = computed(() => {
  return 'composables-test-computed'
})

これだと1ファイルでコンパクトに複数の変数や関数を定義できるのでいいですね。

どこまでデータにアクセスできるのか

どこまでデータ…でいいのかな、例えばuseNuxtAppは使えるのか、同じファイル内のcomposableの変数や関数にはアクセスできるのかは重要な点だと思います。


export const isDev = process.env.NODE_ENV == 'development'

とりあえずこれでv2のisDevっぽいことはできました。

同ファイル内のcomposableの変数や関数にはアクセスにはアクセスできました。


export function composablesTestFunction() {
  if ( isDev ) {
    return 'composables-test-function-dev'
  }
  return 'composables-test-function'
}

export const isDev = process.env.NODE_ENV == 'development'

順不同というかたぶん呼び出し時に参照してるだろうから、こんな↑風に後に書いたものもちゃんと読んでくれました。

useNuxtAppは動きました。 useRouteは動いてなさそう? 空のオブジェクトが返ってきました。

v2でVue.mixinで実装していたものは全て同様のことができました。 isDevとかi18n関連のやつとか。

最後に

Vue.mixinの代わりになるということでだいぶ興奮してしまいましたが、この使い方は非常に危険なんだと思います。 動作に必要な既存のグローバル変数や関数を上書きしてしまうことがあるからです。

だから必ずuseで始まるようにして予約語的な扱いにして、「useで始まるのはcomposablesだから被せるなよ」みたいなニュアンスを含んでそう。 モジュールのcomposablesを見てもだいたいuseで始まってました。

今回は個人でやってるようなプロジェクトで、上書きに問題ないことが簡単に確認とれそうなケースでのみ使えそうな内容だと思います。 たぶんそれでもやらない方がいいんだろうけど。

シェアする: