Open19

Nuxt3勉強ログ

Ryo24Ryo24
// プロジェクト作成
npx nuxi@latest init <プロジェクト名>

// 依存関係をインストール
yarn install

// 実行
yarn dev -o

https://nuxt.com/docs/getting-started/installation

Ryo24Ryo24
プロジェクト直下で tree -I 'node_modules' -f
.
├── ./README.md
├── ./app.vue
├── ./nuxt.config.ts
├── ./package.json
├── ./public
│   └── ./public/favicon.ico
├── ./server
│   └── ./server/tsconfig.json
├── ./tsconfig.json
└── ./yarn.lock

3 directories, 8 files

Ryo24Ryo24

app.vue

<template>
  <div>
    <NuxtPage />
  </div>
</template>

pages/index.vue

<template>
    <h1> Hello World </h1>
</template>

NuxtPagepageindex.vueを呼び出す

Ryo24Ryo24

nuxt.config.ts

hotreload

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },

  vite: {
    server: {
      watch: {
        usePolling: true,
      },
    },
  },
})
Ryo24Ryo24

components

ディレクトリ構造

components/
├── BaseTitle.vue
└── child
    └── ttile.vue

index.vue

<template>
    <h1> Hello World </h1>
    <BaseTitle>
        <h2> Hello World </h2>
        <h3> Hello World </h3>
        <h4> Hello World </h4>
    </BaseTitle>
    <ChildTtile>
        <h2> Hello World </h2>
        <h3> Hello World </h3>
        <h4> Hello World </h4>
    </ChildTtile>
</template>


components直下だとファイル名 / サブディレクトリ下だと<サブディレクトリ名><ファイル名>のアッパーキャメルケースで宣言するとUIコンポーネントとして呼び出せる

Ryo24Ryo24
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

<template>
  <div>
    <p>Some default layout content shared across all pages</p>
    <slot />
  </div>
</template>

<NuxtLayout>でラップすることにより、layoutsディレクトリのレイアウト表示用のvueファイルを適用できる。
https://nuxt.com/docs/guide/directory-structure/layouts

Ryo24Ryo24

Routing

useRoute()で現在のルート(パス)を取得する。
基本的に[xxx].vueのxxxで具体的にパスからxxxの情報を取得するための変数名的な感じで取得する

about/
├── [name].vue
└── index.vue
<script setup lang="ts">
const route = useRoute()
</script>

<template>
    <div> This is the about page {{ route.params.name }}</div>
</template>

<style lang="less" scoped></style>

URL: http://localhost:3000/about/ady

https://nuxt.com/docs/getting-started/routing

Ryo24Ryo24

composables

アプリケーション内で自動でimportされるディレクトリ。
基本ロジックをカプセル化し、再利用しまくるコードを書く感じかな?

export default

JavaScriptのモジュールシステムにおける一部で、特定のモジュールから一つの値(関数、オブジェクト、クラス、プリミティブなど)をエクスポートするために使用されます。
export defaultが指定された値は、他のファイルからimport文を使ってインポートできます。

export default function useTodo() {
    const todoList = ref([]);

    function addTodo(payload) {
        todoList.value = [...todoList.value, payload];
    }

    return {
        todoList,
        addTodo
    }
}
<template>
    <div>
        <button @click="addToList">Add Todo</button>
    </div>
</template>

<script setup lang="ts">
const { todoList, addTodo } = useTodo()

function addToList() {
    addTodo({
        id: todoList.value.length + 1,
        text: 'New Todo',
    })
    console.log('added todoList', todoList.value)
}

</script>

<style lang="scss" scoped></style>

https://ja.vuejs.org/guide/reusability/composables
https://nuxt.com/docs/guide/directory-structure/composables

Ryo24Ryo24

ref()

state管理。なんでも管理できちゃう優れもの。
(範囲が広過ぎて、大量に生やすとめんどくさそう、、、)
一応、テンプレート参照と日本語で言うらしい。

内部実装

export interface Ref<T = any> {
    value: T;
    /**
     * Type differentiator only.
     * We need this to be in public d.ts but don't want it to show up in IDE
     * autocomplete, so we use a private Symbol instead.
     */
    [RefSymbol]: true;
}

https://ja.vuejs.org/guide/essentials/template-refs

Ryo24Ryo24

httpリクエスト

Fetch APIというものが一応ある。だが、基本的にaxiosでいいと思う。
Fetchは必要最小限&サポートしていないブラウザもあるらしく、モダンな形で開発するのが丸そう

https://zenn.dev/syu/articles/9840082d1a6633#axiosによるjsonデータ


Nuxt3では、useFetchを使うのがモダンらしい

https://nuxt.com/docs/migration/component-options#isomorphic-fetch
なんか調べているとNuxt3では基本useFetchを使うらしい。非同期処理の状態をキャッチできるから、投げて結果を取得するのみのaxosよりいいかも?

Ryo24Ryo24

useFetchでGoogle Books APIを叩く

マウントするタイミングで(useFetchの)refresh valueを呼び出すことにより、useFetchが発火する。
(ちなみにonMountedの部分をコメントアウトしても描画される。おそらくbookを参照するタイミングで自動で呼び出されるのかな?)

<template>
    <div>
        <h1> {{ book?.items[0]?.volumeInfo?.title }} </h1>
        <p> {{ book?.items[0]?.volumeInfo?.description }} </p>
        <img :src="book?.items[0]?.volumeInfo?.imageLinks?.thumbnail" />
    </div>
</template>

<script setup lang="ts">

onMounted(() => {
    console.log('mounted')
    refresh()
})


const { data: book, error, refresh, pending } = useFetch(
    'volumes?q=nuxt',
    {
        method: 'GET',
        baseURL: 'https://www.googleapis.com/books/v1/',
    },

)
</script>

<style lang="scss" scoped></style>


個人的にはaxosの書き方の方が好み。やっぱりmethodをベタ書きだとタイポの恐れあるからな、、、わいはGitHub Copilotのおかげで補完されるけど、エディタで補完されなければ地味に辛いし、コード読む時にmethod propertyを確認するのが慣れが必要かな。

Ryo24Ryo24

middleware

ルート(ページ)移動が完了する前に実行するプログラムを定義。
基本的に2種類あり、

  • xxx.global.ts: ルート移動時、絶対呼び出される(以後「global」と呼称)
  • xxx.ts: 移動先に定義していないと呼び出されない(以後、「無印」と呼称)

の2種類がある。
また優先度はglobal > 無印となっている。


基本的な書き方

middleware内でコードを実行する方法

export default defineNuxtRouteMiddleware((to, from) => {
  // to: 遷移元の情報
 // from: 遷移後の情報
})

を定義。

無印のためにpage内で宣言する方法

<script setup lang="ts">
definePageMeta({
    middleware: [
        function (to, from) {
            // to: 遷移元の情報
           // from: 遷移後の情報
       },
        '<ファイル名>', // 「current.ts」なら、current
    ],
});
</script>

https://nuxt.com/docs/guide/directory-structure/middleware