Nuxt3でURLクエリパラメータからデータを取得する方法

前回の下記の記事を参考にして、記事を書いていきます。

https://qiita.com/SKY-HaYaTo/items/ce3f818577a2cc784117

# ディレクトリ構成

```
.
└── NuxtDjangoProject/
    ├── backend/
    │   ├── adminuser
    │   ├── api/
    │   │   ├── migrations/
    │   │   │   └── 0001_initial.py
    │   │   ├── serializer.py
    │   │   ├── urls.py
    │   │   └── views.py
    │   └── todoproject/
    │       ├── settings.py
    │       └── urls.py
    └── frontend/
        ├── components/
        │   ├── footer/
        │   │   └── footer.vue
        │   └── navbar/
        │       └── navbar.vue
        ├── pages/
        │   ├── adminUsers/
        │   │   ├── login/
        │   │   │   └── login.vue
        │   │   ├── registration/
        │   │   │   └── registration.vue
        │   │   ├── updateProfile/
        │   │   │   └── updateProfile.vue
        │   │   └── uploadImageFile/
        │   │       └── uploadImageFile.vue
        │   ├── login/
        │   │   └── login.vue
        │   ├── registration/
        │   │   └── registration.vue
        │   └── index.vue
        ├── .env
        ├── server/
        │   └── uploadthing.ts
        ├── app.vue
        ├── nuxtconfig.ts/
        │   └── package.json
        └── tsxconfig.json

```

# URLクエリ文字列の値を取得する方法

Nuxt 3でURLクエリ文字列からパラメータを取得する方法は、`Vue Router`を利用して簡単に実現できます。`useRoute`というフックを使用して、現在のルートに関連する情報を取得することができます。
具体的には、`$route.query`ではなく、`useRoute`を使って、クエリパラメータを取得します。

## `useRoute`を使ってURLクエリ文字列を取得する方法
Nuxt 3では、`useRoute`フックを使って、現在のルート情報（パス、クエリパラメータなど）を簡単に取得できます。

例: クエリパラメータを取得する

```sample.vue
<script setup lang="ts">
import { useRoute } from 'vue-router'

const route = useRoute()
const imageUrl = route.query.image as string  // クエリパラメータ 'image' を取得
</script>

<template>
  <v-app>
    <!-- 画像URLを表示 -->
    <img :src="imageUrl" alt="Image from query"/>
    <p>Image URL: {{ imageUrl }}</p>
  </v-app>
</template>

```

#### コードの解説
#### useRouteフック
useRouteは、現在のルート情報を提供します。これを使ってクエリパラメータを取得できます。

route.query
route.queryは、クエリパラメータをオブジェクト形式で取得します。例えば、URLが` http://localhost:3000/?image=https://example.com/path/to/image.jpg `の場合、route.query.imageで`"https://example.com/path/to/image.jpg"`というURLを取得できます。

#### as string
TypeScriptを使っている場合、route.query.imageの型はstring | undefinedなので、as stringで型キャストして、imageUrlに格納しています。もしクエリパラメータがない場合、undefinedになることを考慮して、適切なエラーハンドリングを追加することができます。

## クエリパラメータがない場合の処理
クエリパラメータが存在しない場合に備えて、デフォルト値を設定することもできます。

```sample.vue
<script setup lang="ts">
import { useRoute } from 'vue-router'

const route = useRoute()
const imageUrl = route.query.image as string | undefined || 'default_image_url.jpg'  // デフォルト値を設定
</script>

<template>
  <v-app>
    <!-- クエリパラメータがなければデフォルト画像を表示 -->
    <img :src="imageUrl" alt="Image from query"/>
    <p>Image URL: {{ imageUrl }}</p>
  </v-app>
</template>

```

### URLクエリパラメータが変更されたときに自動で反映する
クエリパラメータが変更されるたびに自動で更新されるようにするには、`watch`を使って監視することもできます。
例えば、`image`パラメータが変更されたときに新しいURLを取得する場合は次のように書けます。


```sample.vue
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { watch } from 'vue'

const route = useRoute()

let imageUrl = route.query.image as string | undefined

// クエリパラメータが変わるたびにimageUrlを更新
watch(() => route.query.image, (newValue) => {
  imageUrl = newValue as string | undefined
})
</script>

<template>
  <v-app>
    <img :src="imageUrl" alt="Image from query"/>
    <p>Image URL: {{ imageUrl }}</p>
  </v-app>
</template>

```

ちなみに、UIフレームワーク`Vuetify`を使うと下記のように書けます。

https://vuetifyjs.com/en/components/images/#usage

```frontend/pages/uploadImageFile/uploadImageFile.vue
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { watch } from 'vue'
import { ref } from 'vue';
import axios from 'axios';

const formRef = ref(null);

const route = useRoute();

let imageUrl = route.query.image as string | undefined

// クエリパラメータが変わるたびにimageUrlを更新
watch(() => route.query.image, (newValue) => {
  imageUrl = newValue as string | undefined
})

const onSubmit = async()=>{
    try{
        const formData = new FormData();
        //ユーザIDや、E-mailも追加する。
        formData.append('image',Image.value);

        const response = await axios.post('http://localhost:8000/adminuser/',formData);
        
        if(response.request.status === 200){
            alert('Success to update iamge.');
            console.log(response.data);
        }
    }catch(error){
        alert('Fail to upload image.');
        console.log('Faile to upload image:',error);
    }
}

</script>

<template>
  <v-app>
    <v-main>
        <v-form @submit.prevent="onSubmit" ref="formRef">
            <img 
                :src="imageUrl" 
                alt="Image from query" 
                width="200px"
            />
            <v-img
                v-model="image"
                :width="300"
                aspect-ratio="16/9"
                cover
                :src="imageUrl"
            ></v-img>
            <v-item-group>
                <v-btn 
                    type="button" 
                    color="success" 
                    class="mr-4" 
                    @click="$router.push('/adminUsers/uploadImageFile/uploadImageFile')">
                    Back to PrePage
                </v-btn>
                <v-btn 
                    type="submit" 
                    color="primary" 
                    @click="aa">
                    Update Image
                </v-btn>
            </v-item-group>
        </v-form>
    </v-main>
    
  </v-app>
</template>

```

以上です。

# サイト

https://vuetifyjs.com/en/components/images/#usage