0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

初めてVue3とNuxt3を触ってアプリを開発したのでアプトプットとして残します。

<script setup>

setupの必要性

・コンパイラ処理が事前にされるため、パフォーマンスが早くなる
・export default や setup()などのコードを書かなくても良くなる
・setupがないとエラーになる

template

・templateの中の書き方はReactと同じで

の中に記述が必要(ルート要素を一つにまとめる必要がある)

NuxtPage

・リロードは実際にされずに必要な部分のみ書き換えられる
・ルーティングをすることができる(app.vueで記述)
・PrivateLinkとは?違いとは?

画面遷移ができる
  <NuxtLink to="/price">Price</NuxtLink>

・ルーティングで正しく動作しないことが稀にある

nuxt.config.ts
// この記述がないと、正しいルーティング動作がされない場合がある
  app: {
    baseURL: '/', // ベース URL を設定
  },

動的ルーティング

・ファイル名は下記のように記述する

[id].vue

idの取り出し方は下記のように記述する

[user_id]の場合は{{$route.params.user_id}}とつけた名前によって変わる
{{$route.params.id}}

パラメータ値のバリデーション

パラメーター値によって取得するページでバリデーション処理をする
ミドルウェアでするべきどうかは要確認が必要!

<script setup>
  //ルーティングパラメータ値のidをバリデーションする
  // エラーの場合は404ページを表示
  definePageMeta({
    validate:async(route) => {
      return /^\d+$/.test(route.params.id)
    }
  })
</script>

[id]page.vue 左のように書くのはダメみたい->規則を把握

レイアウト

・NuxtLayoutの基本的な仕組み
・layoutsディレクトリに保存され、layouts.default.vueに保存される
カスタムレイアウトの場合はlayouts内に追加する

app.vue
<NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
layouts/default.vue
<template>
  <div>
    <div class="container">
      <slot></slot>
      <footer>
        &copy; proglus.jp
      </footer>
    </div>
  </div>
</template>

<style scoped>
.container {
  max-width: 800px;
  margin: 0 auto;
  padding: 0 20px;
  color: red;
}
footer {
  background-color: orange;
  color: white;
  text-align: center;
}
</style>

・NuxtLayoutはスロット(slot)を使用して、コンテンツをレイアウトに埋め込むことができる

ブラウザのヘッダーに指定する

app.vueにuseHead()で指定できる

useHead({
  title: '学習進捗管理',
  link:
  meta: [
    {
      name: 'description',
      content: 'Nuxt.js is a framework for creating Vue.js applications.'
    }
  ]
})

linkを追加するとエラーになったので要確認

templateでfor文

 <ul>
      <li v-for="user in users" :key="user.id">
        {{ user.id }}, {{ user.name }}
      </li>
</ul>

非同期処理

useFetchで簡単に行える(デフォルトGET)

const {data:users} = await useFetch('https://jsonplaceholder.typicode.com/users')

例外を出す

const {data:users, error} = await useFetch('https://jsonplaceholder.typicode.com/userss');
console.log(error.value)
if (error.value) {
  throw createError({statusCode: 404, statusMessage: 'APIエラーが発生しました'});
}

画像を表示(assets)

  <img src="~/assets/cat.jpg" alt="猫の画像">

生的ファイルを検索エンジンに見られないようにする方法

全ての検索エンジンに対してサイト全体をクロールを拒否する設定をrobots.txt記述
public/robots.txt (デフォルトでファイルは作成されるがコードは自分で記述が必要)

User-agent: *
Disallow: /

状態管理

 // 初期値にtitleを設定 (初期値がないとラインダムな値が設定される)')
  const title= useState('title', () => '学習進捗管理')

composables(グローバル変数)

auto-importが行われるディレクトリでcomposablesディレクトリ配下に設定されたファイルが自動的にインポートされる

composables/index.ts
export const useTitle = () => useState('title', ()=> '学習進捗管理アプリ')
呼び出しもと
  const title = useTitle()

Vue3勉強

ディレクティブ

v-bind

v-bindを使うと状態の変化によってHTML属性を変えることができる(動的に属性を変えることが可能)
vueでは、aタグにurlを変数から記載するには、普通の書き方では遷移することはできずにv-bindを使用する必要がある

 <a v-bind:href="url">詳細</a>

また省略することも可能

 <a :href="url">詳細</a>

v-on

イベントによって関数を呼ぶことができる
(発火処理)

 <button v-on:click="buy">買う</button>

短縮系

 <button @click="buy">買う</button>

リアクティブな値

templateが再度読み込まれるのは、コンポーネントが再描画されるときです。(リアクティブな値が変わった時)
そのため、リアクティブな値を使用しないと再描画されない

ref

単一的な値(stringやnumber)

import {ref} from 'vue';
  初期化
 const food1 = ref('');
 // 最代入
 food1.value = event.target.value;

reactive

複数の値を同時に行いたい(オブジェクトや配列)

import {ref, reactive} from 'vue';
const item1 = reactive({
  food: 'ラーメン',
  price: 400,
})
  item1.food = event.target.value;

v-model

:valueの短縮系で
v-on:inputも必要なくなる
双方向のデータバインディングを行い
v-modelで定義された変数と、Vueインスタンスのデータプロパティの変数の紐付けを行い、どちらかが変わるともう一方も変わる挙動をする

一日悩ましたこと

クライアントサイドレンダリングとサーバーサイドレンダリングの違い
下記の二つのAPi通信があった場合にリロード後に1の方は正しい挙動だが、2の方が
通信が行われなかった。

1 const {data:users, error} = await useFetch('https://jsonplaceholder.typicode.com/users');
2 const { data: studytimeData, error: studytimeError } = await useFetch('http://localhost/api/studytime/fetch');

原因はnuxtの設定ファイル(nuxt.config.ts)だと思ったが、違っていて
クライアントサイドレンダリングが原因だとわかった。
下記のように設定すると正しい挙動をした

if (process.client) {
  const { data: studytimeData, error: studytimeError } = await useFetch('http://localhost/api/studytime/fetch');
}

理由はnuxtではリロード後に最初にSSRが実行されて、その後にCSRが実行される。
今回の場合、1はSSRとCSR両方で成功するが、2の場合はlocalhostのため、SSRは自身のサーバーを指すため、失敗して、CSRでは成功する。
しかし、SSRで失敗したことがCSRで成功したことに上書きされて、失敗している可能性が高い。
ちなみにSSRの場合はサーバー側での処理のため、ブラウザでデバック結果が表示されないので注意

onMounted

onMounted()はライフライクルのマウント時のCSRで呼ばれる
これは検証済み(ログがターミナルに表示されない)

onMounted(() => {
  // クライアントの場合
  if (process.client) {
    console.log('mounted')
   fetchStudyData()
  }
  // SSRの場合
  if (process.server) {
    console.log('server')
  }
})

Nuxtライフライくる

リロードまたは初回アクセス
        |
        v
    サーバーにリクエスト
        |
        v
 サーバー側でSSRフェーズ開始
 ┌────────────────────┐
 | beforeCreate (サーバー) |
 | created (サーバー)      |
 | beforeMount (サーバー) |
 └────────────────────┘
        |
        v
 サーバーがHTMLを生成
        |
        v
 HTMLをブラウザに送信
        |
        v
 ブラウザがHTMLを表示
        |
        v
 クライアント側でJavaScript実行開始
 ┌────────────────────┐
 | beforeCreate (クライアント) |
 | created (クライアント)      |
 | beforeMount (クライアント) |
 └────────────────────┘
        |
        v
 ハイドレーション実行
        |
        v
 クライアント側でmounted実行
        |
        v
 ユーザー操作に応じて更新
 ┌────────────────────┐
 | beforeUpdate                 |
 | updated                      |
 | beforeDestroy                |
 | destroyed                    |
 └────────────────────┘

export default {
  async setup() {
    // サーバー側とクライアント側両方で実行
    console.log('beforeCreate');

    // created相当
    console.log('created');

    // beforeMount相当
    onBeforeMount(() => {
      console.log('beforeMount');
    });

    // mounted相当
    onMounted(() => {
      console.log('mounted');
    });

    // 更新時のフック
    watchEffect(() => {
      // データが変更されたときにbeforeUpdateとupdatedが実行されます
    });

    // 破棄時のフック
    onBeforeUnmount(() => {
      console.log('beforeDestroy');
    });

    onUnmounted(() => {
      console.log('destroyed');
    });
  }
}

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?