はじめに
この記事はVue.jsに関して学習した内容の備忘録です
誤りや改善点があれば都度、修正および更新予定です
Vue.jsとコンポーネント
コンポーネントとは『部品』を意味するVue.jsでは非常に重要な概念で、アプリケーションの機能を小さな部分に分割して再利用可能にすることでSPA
を可能にしています
SPA(シングルページアプリケーション)とは?
- ひとつのページだけを使って動くアプリのことを指します
- ページ全体を再読み込みせずに必要な部分だけを更新することができます
- ページ更新時、いちいち真っ白にすることなく画面を切り替えできます
- 具体的にはショッピングサイトやSNS、商品管理システムなどで用いられています
MPA マルチページアプリケーション(MPA)も作成可能
- 各ページが複数のファイル(HTMLなど)で個々に独立しているページも作成可能です
また、『Vue Router』などのルーティングライブラリを使用すれば、リクエストされたURLに応じて適切なコンポーネントを表示し、多様なWebサイトを構築します。
ディレクトリ構成図
vue-project // プロジェクトのルートディレクトリ
├── node_modules // インストールされたパッケージやライブラリが格納されるディレクトリ
├── public // 公開される静的なファイル(HTMLや画像など)を配置するディレクトリ
│ ├── favicon.ico // ブラウザのタブに表示されるアイコンのファイル
│ └── index.html // アプリケーションのメインHTMLファイルで、Vue.jsが描画するベースとなる
├── src // ソースコードを配置するメインのディレクトリ
│ ├── assets // 画像やスタイルシートなどの静的リソースを格納する場所
│ ├── components // Vueコンポーネント(再利用可能なUIパーツ)を配置するディレクトリ
│ ├── views // 各画面やページを構成するVueファイルを配置するディレクトリ
│ │ ├── HomeView.vue // ホーム画面のコンポーネント
│ │ ├── AboutView.vue // About画面のコンポーネント
│ │ └── ・・・ // 他の画面コンポーネント
│ ├── router // ルーティング設定を管理するディレクトリ
│ │ └── index.js // ルーティング設定を記述するファイル
│ ├── main.js // アプリケーションのエントリーポイント(起点)となるJavaScriptファイル
│ └── App.vue // アプリケーション全体のルートコンポーネント
├── .gitignore // Gitに追跡させたくないファイルやディレクトリを指定する設定ファイル
├── babel.config.js // Babelの設定ファイル。JavaScriptのコードを変換するための設定を記述
├── jsconfig.json // JavaScriptの設定ファイルで、エディタの補完機能や型チェックに関する設定を記述
├── package-lock.json // インストールされたパッケージの正確なバージョンを記録し、再現性を保つためのファイル
├── package.json // プロジェクトの依存関係やスクリプト、メタデータを記述するファイル
├── README.md // プロジェクトの概要や設定方法、使い方などの説明が書かれたファイル
└── vue.config.js // Vue CLIのプロジェクト設定をカスタマイズするための設定ファイル
ブラウザへコンポーネントを表示させる仕組み(概要)
main.jsはVue.jsアプリケーションの起点となるファイルで、index.js(ルーティング設定)とApp.vue(基本レイアウト)をインポートします。
ユーザーがリクエストしたURLに基づいて、App.vueは必要な画面をviewsディレクトリからインポートします。さらに、views内のVueファイルは、必要なコンポーネントをcomponentsディレクトリからインポートすることで、ブラウザに表示する内容を提供します。
main.jsの詳細
Vue.jsフレームワークにはコンポーネントやルーティングなど様々な機能が含まれておりますが、各々の機能はmain.jsでインスタンス化しなければそれらは使用することができません
// Vueのライブラリを読み込み
import Vue from 'vue';
// アプリのメインとなる部分を読み込み
import App from './App.vue';
// ルーティング機能を読み込み(必要に応じて)
import router from './router';
// Vueのインスタンスを作成
new Vue({
// 使うコンポーネントを指定
render: h => h(App),
router, // ルーティング機能をここで使う
}).$mount('#app'); // 指定した場所に表示
上記の例では、ルーティングおよびライブラリ、コンポーネントを
使用可能な状態にしています
App.vueとmain.jsの役割
Vue.jsではヘッダーやフッター、メインコンテンツやサブコンテンツなど、リクエストされたURLに応じてApp.vueに『コンポーネント』をインポート
します
main.jsはApp.vueをインポート
することでApp.vueの内容をブラウザに表示します
Vueファイルとは
Vueファイル(.vueファイル)はHTML、CSS、JavaScript
が一つにまとめられたファイル形式です。
Vueファイルの構造について
Vueファイル以下の3つの主要なセクションに分かれています
-
template
- HTML構造を定義します
-
script
- JSのプログラムや変数に与えるデータを定義します
-
style
- cssを定義します
※ 必ず3つすべてが必要ではなく、コンポーネントの目的や内容に応じて必要なタグだけを記述できます
<template>
<div id="app">
<header-component /> <!-- ヘッダーコンポーネントを表示 -->
<main>
<h1>ようこそ!</h1>
<p>Vue.jsアプリケーションです。</p>
<button @click="toggleMessage">{{ buttonLabel }}</button> <!-- ボタンをクリックでメッセージの表示を切り替え -->
<p v-if="showMessage">ON/OFFでメッセージを表示</p>
</main>
<footer-component /> <!-- フッターコンポーネントを表示 -->
</div>
</template>
<script>
import HeaderComponent from './components/HeaderComponent.vue'; // ヘッダーコンポーネントをインポート
import FooterComponent from './components/FooterComponent.vue'; // フッターコンポーネントをインポート
export default {
name: 'App',
components: {
HeaderComponent, // ヘッダーコンポーネントを登録
FooterComponent // フッターコンポーネントを登録
},
data() {
return {
showMessage: false // メッセージを表示するかどうかのフラグ
};
},
computed: {
buttonLabel() {
return this.showMessage ? '(true)メッセージを非表示' : '(false)メッセージを表示';
}
},
methods: {
toggleMessage() {
this.showMessage = !this.showMessage; // メッセージの表示/非表示を切り替え
}
}
};
</script>
<style scoped>
/* 基本的なスタイルを追加 */
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
App.vueのtemplateセクションには、他のコンポーネントをインポートして組み合わせるだけでなく、アプリケーション全体のレイアウトや共通の要素を記述することもあります
用語説明
コンポーネント
コンポーネントは、再利用可能なUI(ユーザーインターフェース)の部品を意味しており、各コンポーネントは独立していて特定の機能や表示を担当します。
例えば、ヘッダーやフッターをコンポーネントとして作成すると、それらを他のページでも簡単に再利用できるようになります。
これにより、同じコードを何度も書く必要がなくなり効率的な開発が可能になります。
マウントする
コンポーネントが特定の場所に取り付けられ(import)、ブラウザに描画されることを意味します。以下の例ではコンポーネントがブラウザへ表示された直後に実行されるメソッド(mountedメソッド)を使ってログを出力しています
<script>
export default {
name: 'MyComponent',
data() {
return {
message: 'Hello, Vue!', // 初期メッセージ
};
},
mounted() {
// コンポーネントがマウントされた後に実行される処理
console.log('コンポーネントがマウントされました!');
// ここでAPIからデータを取得することもできます。
this.fetchData(); // データを取得するメソッドを呼び出す例
},
methods: {
fetchData() {
// ここにデータ取得の処理を書くことができます
console.log('データを取得中...');
// 例: axiosを使ってAPIからデータを取得するなど
},
},
};
</script>
components (読み方:コンポーネント)
componentsプロパティは親コンポーネントが子コンポーネントを使用できるようにするため、子コンポーネントをリスト化して登録しています
componentsプロパティを使用しない場合、テンプレート内で子コンポーネントを使用しようとしても、Vueはそれを認識できないためエラーが発生します
<template>
<div>
<h1>親コンポーネント</h1>
<ChildComponent />
</div>
</template>
<script>
// 子コンポーネントをインポート
import ChildComponent from './ChildComponent.vue';
export default {
name: 'ParentComponent', // 親コンポーネントの名前
components: {
ChildComponent, // 子コンポーネントを登録
},
};
</script>
<style scoped>
/* 必要に応じてスタイルを追加 */
</style>
<template>
<div>
<h2>子コンポーネント</h2>
<p>これは子コンポーネントです。</p>
</div>
</template>
<script>
export default {
name: 'ChildComponent', // 子コンポーネントの名前
};
</script>
<style scoped>
/* 必要に応じてスタイルを追加 */
</style>
export default (読み方:エクスポート デフォルト)
Vue.jsではexport default
を使用することで、コンポーネント全体(template、script、styleを含む)を他のファイルからインポート可能な状態にします。
export default
が存在しない場合、そのコンポーネント(またはモジュール)は他のファイルでインポートできなくなります。
name
必須のプロパティではありませんが、Vueコンポーネントに一意の識別名を付けるために使います。これにより、デバッグ時にコンポーネントを簡単に特定でき、再帰的に自分自身を呼び出す際に役立ちます。
一つのコンポーネントには、一意の名前しか設定できないため、1ファイルにつき1つのみ設定できます。
name プロパティ
はファイル名と一致させ、export default のオブジェクトの最初に追加することが一般的です
<template>
<div>
<!-- isVisibleがtrueの場合にメッセージを表示 -->
<div v-if="isVisible">
<p>表示されています!</p>
</div>
<!-- isVisibleがfalseの場合は、再帰的に自分自身を呼び出す -->
<MyComponent v-if="!isVisible" :isVisible="true" />
</div>
</template>
<script>
export default {
name: 'MyComponent', // コンポーネントの名前
props: {
isVisible: {
type: Boolean,
required: true, // このプロパティは必須
},
},
};
</script>
<style scoped>
/* 必要に応じてスタイルを追加 */
</style>
data
data メソッド
はVue コンポーネント内で扱う『変数』を意味しており、変数の宣言および、初期値の代入、true/falseを扱うブール値の定義を設定できるメソッドです。
dataメソッドに変数を定義しないと、その変数はコンポーネント内で使用できません。ここで定義された変数だけがテンプレート内やメソッド内で参照・変更できます。
- もし
dataメソッド
で変数を宣言しないと、具体的に以下のようなことが起こります- テンプレート内でv-if="someVar"のように使用しても、someVarがdataメソッドで宣言されていない場合、Vueはその変数を見つけられず、エラーが発生します
- dataメソッドに定義されていない変数は値が変わっても画面が自動で更新されません
<template>
<div>
<p>カウント: {{ count }}</p>
<button @click="increment">カウントを増やす</button>
</div>
</template>
<script>
export default {
name: 'CounterComponent', // コンポーネントの名前
data() {
return {
count: 0, // 初期値を0に設定
};
},
methods: {
increment() {
this.count++; // countを1増やす
},
},
};
</script>
<style scoped>
/* 必要に応じてスタイルを追加 */
</style>
methods (読み方:メソッド)
Vueコンポーネント内で定義されるメソッド(関数)を管理するためのオブジェクトです。ボタンをクリックしたときに変数の値を変更したり、HTTPリクエストを送信できるAxiosやFetchなどもmethods
内に記述します。
例えば、Vueコンポーネントのmethods
内でaxiosを使ってAPIにリクエストを送信し、その結果をdataで定義した変数に保存することで、コンポーネントの表示内容を動的に更新することができます。
- もし
methods
の範囲外でメソッドを記述した場合、以下のようなことが起こります- テンプレート内(例えば@click)で呼び出せない
- axiosを使っても変数の値を更新できない
- (単純にリクエストを送ってその結果を使うことは可能です)
ディレティブについて
ディレクティブ
とはVue.jsで特定のHTML要素に対して動的な振る舞いを持たせるための特別なマークアップのことです。通常はHTMLの属性のように見えますが、Vue.jsに特有の機能を実現するためのものです。ディレクティブは「v-」という接頭辞を持ち、Vue.jsによって解釈されます。
ディレクティブ
は要素やコンポーネントに対して動的な変更や反応を追加するために使用されます。
v-if
HTMLの要素に対して、要素の表示/非表示を切り替えます。条件が true のときだけ要素が表示され、false のときは非表示になります。
true/falseの判断はtemplate内の変数に存在するブール値(真偽値)決定され、その条件式はコンポーネント内の変数やメソッドで制御されます
<template>
<div>
<h1>v-ifの例</h1>
<!-- isVisibleがtrueの時に表示される -->
<div v-if="isVisible">
<p>表示されています!</p>
</div>
<!-- isVisibleがfalseの時に表示される -->
<div v-else>
<p>非表示です!</p>
</div>
<!-- ボタンをクリックすると、isVisibleの値を切り替える -->
<button @click="toggleVisibility">表示/非表示</button>
</div>
</template>
<script>
export default {
name: 'VisibilityToggle',
data() {
return {
isVisible: true, // 初期状態は表示されている
};
},
methods: {
toggleVisibility() {
this.isVisible = !this.isVisible; // isVisibleの値を反転させる
},
},
};
</script>
<style scoped>
/* 必要に応じてスタイルを追加 */
</style>
v-else
v-if とセットで使用し、v-if の条件がfalse(偽)の場合にのみ表示される要素を定義します。ただしv-else は、v-if のすぐ後に続けて書く必要があります。
<div v-if="isVisible">
表示されています!
</div>
<!-- この間に別の要素が入っているため、v-else は正しく動作しません -->
<p>このテキストが間に入っています。</p>
<div v-else>
表示されていません。
</div>
<div v-if="isVisible">
表示されています!
</div>
<div v-else>
表示されていません。
</div>
v-for
配列やオブジェクトを使って、要素を繰り返し表示させます。ループのような動作をするディレクティブです。
<template>
<div>
<h1>アイテムリスト</h1>
<ul>
<!-- items配列の各要素に対してループを作成 -->
<li v-for="item in items" :key="item.id">
{{ item.name }} - {{ item.price }}円
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'ItemList',
data() {
return {
// アイテムの配列
items: [
{ id: 1, name: 'リンゴ', price: 100 },
{ id: 2, name: 'バナナ', price: 200 },
{ id: 3, name: 'オレンジ', price: 150 },
],
};
},
};
</script>
<style scoped>
/* 必要に応じてスタイルを追加 */
</style>
item in items
items配列の各要素をitemという名前の変数に割り当て、ループ処理を行います。これにより、配列内の各アイテムにアクセスできます。
:key="item.id"
Vueが各要素を識別するためのユニークな値です。この場合、各アイテムのidをキーとして使います(記述しなくてもv-forは利用できますが、記述することでパフォーマンスが向上させ、予期しない動作を防ぎます)
v-bind
データとHTML要素の属性(例えば、src属性)を結び付けることを意味します。例えばクラス名やスタイル、要素の属性値をデータに応じて変更できます。省略形は「:」です。
『バインド』とはデータをある要素やプロパティに結び付けることを指します
<template>
<img v-bind:src="imageUrl" alt="画像">
<img :src="imageUrl" alt="画像"> <!-- 短縮系の場合-->
</template>
<script>
export default {
data() {
return {
imageUrl: 'https://example.com/image.jpg', // 画像のURL
};
},
};
</script>
v-model
Vue.jsで双方向のデータバインディングを行うためのディレクティブです。これは、フォーム要素(入力フィールド、チェックボックス、セレクトボックスなど)と Vue インスタンスのデータを連動させるために使われます。これにより、フォームに入力した内容が自動的に Vue インスタンスのデータに反映され、逆に Vue インスタンスのデータを変更するとフォームの表示内容も変わります。
<template>
<div>
<!-- v-modelを使って入力フィールドとmessageというデータを結びつけます -->
<input v-model="message" placeholder="メッセージを入力してください">
<p>あなたが入力したメッセージ: {{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '' // 初期値は空文字
};
}
}
</script>
v-on
ボタンがクリックされたときや入力フィールドの内容が変更されたときなど、methods
に用意した関数などを実行できるディレクティブです
<template>
<div>
<!-- v-onでclickイベントを監視し、handleClickメソッドを実行 -->
<button v-on:click="handleClick">クリック数をカウント</button>
<p>クリック回数: {{ count }}</p>
<div v-on:mouseover="handleMouseOver">マウスを乗せてください</div>
<p>マウスカーソルが載せられた数: {{ over }}</p>
</div>
</template>
<script>
export default {
data() {
return {
count: 0, // 初期値は0
over: 0 // 初期値は0
};
},
methods: {
// ボタンがクリックされたときに呼び出されるメソッド
handleClick() {
this.count++; // countを1増やす
},
handleMouseOver() {
this.over++; // countを1増やす
}
}
}
</script>
App.vueとコンポーネントの親子関係
App.vueはVue.jsの親コンポーネント
として、アプリ全体の『起点』となります。ここで子コンポーネント
をインポートし、アプリの構成を組み立てます。
データは親コンポーネントから受け渡す
大規模アプリでは、データの取得と利用を親と子に分けることが推奨されます。
親コンポーネントがAPIからデータを取得し、それを子コンポーネントに渡すことでデータの一方向の流れが実現され、アプリ全体でのデータ管理が簡単で一貫性を持たせることができます。
一方、構造が単純な小規模アプリでは、コンポーネント数が少なく、データの流れが明確なため、必ずしも親コンポーネントを必要とはなりません。また、親コンポーネントはApp.vueに限らず、子コンポーネントが孫コンポーネントをインポートする場合でもデータの受け渡しが可能です。
<template>
<div>
<h1>親コンポーネント</h1>
<ChildComponent :message="parentMessage" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent,
},
data() {
return {
parentMessage: 'こんにちは、子コンポーネント!',
};
},
};
</script>
<template>
<div>
<h2>子コンポーネント</h2>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true, // 必須のプロパティ
},
},
};
</script>
データの渡し方
親コンポーネントのtemplate内で子コンポーネントを呼び出し、その際に渡したい変数を設定します。
v-bind(省略形の:を使うこともできます)
を用いることでscriptタグのdataメソッド変数を子コンポーネントのpropsとして連携させることができます。
import
他のファイルで定義された機能やデータを現在のファイルに取り込むことができます。import文は伝手にファイルの最上部に記述する必要があり、export default
の外に書くことがルールとなっています。したがってexport default の内部に import を書くと、構文エラーになります。
export default
コンポーネント(template、script、style を含む)を外部にエクスポートすることで、他のファイルからインポートができるようにします
components
インポートしたコンポーネントを使用するためには、必ずcomponentsオプションで宣言する必要があります。これにより、親コンポーネントの内でその子コンポーネントを利用できるようになります。
props
Vue.jsにおける親コンポーネントと子コンポーネントの間でデータを受け渡すための仕組みです。子コンポーネントはpropsオプションを定義することでデータを受け取ることができます
子コンポーネントでpropsオプションを定義してデータを受け取る際は、必ず変数名とデータ型を一致させる必要があります。propsオプションにデータ型や変数名が正しく記述されていない場合、エラーが発生します。
<!-- ParentComponent.vue -->
<template>
<div>
<h1>親コンポーネント</h1>
<!-- データを子コンポーネントに渡す -->
<ChildComponent
:message="parentMessage"
:count="parentCount"
/>
</div>
</template>
<script>
// 子コンポーネントをインポート
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent, // 子コンポーネントを登録
},
data() {
return {
parentMessage: '子コンポーネント!', // 渡したいデータ1
parentCount: 5, // 渡したいデータ2
};
},
};
</script>
<!-- ChildComponent.vue -->
<template>
<div>
<h2>子コンポーネント</h2>
<p>{{ message }}</p> <!-- 親から受け取ったメッセージを表示 -->
<p>カウント: {{ count }}</p> <!-- 親から受け取ったカウントを表示 -->
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true, // 必須のプロパティ
},
count: {
type: Number,
},
},
};
</script>
APIにHTTPリクエストを送信する方法
APIにHTTPリクエストを送信するライブラリは複数存在しますが、この記事ではAxiosを使った送信方法を学習しました
Axiosとは
Axiosは、JavaScriptでHTTPリクエストを簡単に行うためのライブラリです。主に、APIとやり取りするために使用されます。
Axiosをインストールする
Axiosを使用するには、Axiosのライブラリをインストールする必要があります。
カレントディレクトリをプロジェクトに合わせてからコマンドでインストールできます。
CD プロジェクトのパス
npm install axios
Axiosの使い方
AxiosをJavaScriptで使うためには、まずライブラリからAxiosをインポートする必要があります
<template>
</template>
<script>
import axios from 'axios';
</script>
AxiosでGETやPOSTなどのリクエストを送信する場合は次のように記述することで送信が可能です
<script>
import axios from 'axios';
// GETの場合
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data); // 取得したデータを表示
})
.catch(error => {
console.error('エラーが発生しました:', error); // エラー時の処理
});
// POSTの場合
axios.post('https://api.example.com/users', {
name: 'John Doe',
email: 'john@example.com'
})
.then(response => {
console.log('データが送信されました:', response.data);
})
.catch(error => {
console.error('エラーが発生しました:', error);
});
</script>
axios.get(url)
指定したURLに対してGETリクエストを送ります。
.then()
axiosのHTTPリクエストが成功し、レスポンスが帰った場合に実行される処理を指定するメソッドです
response => {...}
response
はAPIから返ってきたレスポンスを指しており、アロー関数を使うことでresponse
を引数にして関数を展開することができます
(アロー関数について補足)
通常の関数定義の短縮形であり、次のようにfunction
とreturn
の宣言を省略することができます
// 従来の関数
function add(a, b) {
return a + b;
}
// アロー関数
const add = (a, b) => a + b;
// 複数行でアロー関数を使う場合は {}を使用します
// 複数業で戻り値を得るにはreturn文も必要です
const add = (a, b) => {
return a + b; // 返り値を明示的に指定
};
<script>
// 以下にはreturn文がありませんが
//アロー関数が複数行の際、何らかの値を返す必要がある場合はreturn 文を使う必要があります
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data); // 取得したデータを表示
})
.catch(error => {
console.error('エラーが発生しました:', error); // エラー時の処理
});
</script>
.catch(error => { ... })
HTTPリクエストが失敗した場合に実行される処理を記述するメソッドです。このリクエスト失敗には、ネットワークエラーやサーバーからのエラーレスポンスが含まれます(例:404や500エラー)
error
はリクエストが失敗した際に自動的に渡されるエラーオブジェクトであり、エラーメッセージやステータスコードなどの情報が含まれています。
console.error('エラーが発生しました:', error);
は、エラーメッセージとエラーオブジェクト全体を出力しています。
axios.post(url, data)
指定したURLに対してPOSTリクエストを送ります。data にはサーバーに送信するデータをオブジェクト形式で渡します。データはプロパティと値のペアを{}で囲む必要があります
axios.post('https://api.example.com/users', {
name: 'John Doe',
email: 'john@example.com'
})
.then(response => {
console.log('データが送信されました:', response.data);
})
.catch(error => {
console.error('エラーが発生しました:', error);
});
(オブジェクト形式についての補足)
オブジェクト形式のデータは中括弧 {} で囲まれたキーと値のペアから構成されます。
const person = {
name: '太郎', // キー 'name' に対する値 '太郎'
age: 25, // キー 'age' に対する値 25
isStudent: false // キー 'isStudent' に対する値 false
};
(オブジェクト形式からデータを取り出す方法)
オブジェクト形式のプロパティには、ドット .
またはブラケット []
表記を使ってアクセスできます
console.log(person.name); // '太郎' と表示
console.log(person['age']); // 25 と表示
AxiosでAPIからレスポンスを取得した場合の例
<template>
<div>
<h1>ユーザーリスト</h1>
<ul>
<!-- users 配列のデータを繰り返し処理して表示 -->
<li v-for="user in users" :key="user.id">
{{ user.name }} - {{ user.email }}
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
users: [] // APIから取得したユーザー情報を格納する配列
};
},
created() {
// コンポーネントが作成されたときにAPIリクエストを送信
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
this.users = response.data; // 取得したデータを users 配列に代入
})
.catch(error => {
console.error('データの取得に失敗しました:', error);
});
}
}
</script>
response.data
responseオブジェクトのdataプロパティ
です。
APIからのレスポンスを受け取った際、response オブジェクト
にはいくつかのプロパティ
が含まれており、その中の data プロパティ
には、APIから送られてきた実際のデータが格納
されています。
レスポンスがネストされたデータの例
ネスト
とは配列の中に別の配列が入った状態を指します。LaravelのAPIでは一般的にJson形式でデータを返すためリレーション関係のテーブルデータ
をAPI経由で取得した場合、一般的にそのデータはネスト
されています
- users テーブル(親)
- posts テーブル(子、ユーザーに関連する投稿)
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"posts": [
{
"id": 101,
"title": "My First Post",
"content": "This is the content of my first post."
},
{
"id": 102,
"title": "Another Post",
"content": "This is another post content."
}
]
}
- posts は users テーブルに関連する投稿データを表し、ユーザーの情報(id、name、email)の中にネストされた形で含まれています
- 各投稿(posts)もオブジェクトの配列として、ユーザーに対してネストされています
ネストされたデータへアクセスする方法
このようなリレーションデータをJavaScriptやVue.jsで処理する際、ネストされたデータにアクセスするには、ドット記法を使って階層をたどります。
// ユーザーの名前を取得
console.log(user.name); // "John Doe"
// ユーザーの最初の投稿のタイトルを取得
console.log(user.posts[0].title); // "My First Post"
Vue.jsでネストされたデータを使う方法
<template>
<div>
<h1>ユーザー情報</h1>
<p>名前: {{ user.name }}</p>
<p>都市: {{ user.address.city }}</p>
<h2>投稿一覧</h2>
<ul>
<li v-for="post in user.posts" :key="post.id">
<h3>{{ post.title }}</h3>
<p>{{ post.content }}</p>
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {
name: '',
address: {
city: ''
},
posts: []
}
};
},
created() {
axios.get('https://api.example.com/user')
.then(response => {
this.user = response.data.user; // ネストされたデータを user に代入
})
.catch(error => {
console.error('データの取得に失敗しました:', error);
});
}
}
</script>
{
"user": {
"name": "John Doe",
"address": {
"city": "Tokyo"
},
"posts": [
{
"id": 1,
"title": "初めての投稿",
"content": "これは私の初めての投稿です。"
},
{
"id": 2,
"title": "次の投稿",
"content": "次の投稿の内容です。"
}
]
}
}
API → 親コンポーネント → 子コンポーネント(例)
<template>
<div>
<h1>ユーザー情報</h1>
<p>名前: {{ user.name }}</p>
<p>都市: {{ user.address.city }}</p>
<h2>投稿一覧</h2>
<PostList :posts="user.posts" />
</div>
</template>
<script>
import axios from 'axios';
import PostList from './PostList.vue'; // 子コンポーネントをインポート
export default {
components: {
PostList // 子コンポーネントを登録
},
data() {
return {
user: {
name: '',
address: {
city: ''
},
posts: [] // 投稿データを格納する配列
}
};
},
created() {
// APIからユーザー情報を取得
axios.get('https://api.example.com/user')
.then(response => {
this.user = response.data.user; // ユーザー情報を格納
})
.catch(error => {
console.error('データの取得に失敗しました:', error);
});
}
}
</script>
<template>
<div>
<ul>
<li v-for="post in posts" :key="post.id">
<h3>{{ post.title }}</h3>
<p>{{ post.content }}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
posts: {
type: Array,
required: true // 必須のプロパティ
}
}
}
</script>
Vueのルーティングについて
ルーティングはユーザーのリクエストに応じて特定のページやコンポーネントを表示するための仕組みです。Vue.jsのプロジェクトを新規作成する際、オプションの設定によってはルーティングに必要なライブラリやディレクトリが作成されていない可能性があるため、ライブラリやディレクトリが存在しない場合は以下の手順でライブラリをインストールし、ディレクトリとファイルを作成する必要があります
Vue Routerのインストール
Vue Routerを利用するためにはVue Router
というライブラリが必要です。以下のコマンドで最新のVue Routerをインストールできます
npm install vue-router
ルーティングのファイル
ルーティングは一般的にsrc/router/index.js
へ記述することになりますが、プロジェクトを新規作成する際の設定によっては、ルーティングに関するディレクトリとファイルが作成されないため、手動でディレクトリとファイルを作成する場合があります。
my-project/
├── src/
│ ├── assets/
│ ├── components/
│ ├── router // ルーティングのディレクトリ
│ │ └── index.js // ルーティングの設定ファイル
│ ├── views/
│ ├── App.vue
│ └── main.js
├── public/
├── package.json
└── ...
ディレクトリとファイル生成のコマンド
mkdir src/router
touch src/router/index.js
router/index.jsの基本的な記述
router/index.jsファイルにルーティングの設定を行った場合の基本的な例です
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
import
ルーティングの機能を使用するためには、まずそのファイルに対して Vue Router ライブラリ
およびルーティング先の Vue ファイル
をインポートする必要があります。vue-router からは createRouter
と createWebHistory
という複数の機能をインポートしているため、これらの名前を波括弧 {} で囲む必要があります。
Vueファイル(コンポーネント)をimportする場合、以下のように任意の名前をつけることができます。ただしファイル名とインポート名が一致しない場合、コードの可読性が低下する可能性があるため推奨はされません
import MainPage from '../views/HomeView.vue';
const routes = [
{
path: '/',
name: 'home',
component: MainPage // インポート名がMainPage
}
];
name
nameでつけられた名称はリンクの生成に使われます
router-link
を使用することで、URLを直接指定せずに、nameで設定したルーティングに誘導できます。
<router-link :to="{ name: 'about' }">About</router-link>
:to="{ name: 'about' }"
Vue Routerを使ったナビゲーションの非常に便利な方法であり、特にアプリケーションのルートが多い場合に役立ちます。名前付きルートを使用することで、URLの変更やリファクタリングを行った際も、リンク先を一括で変更することができるため、メンテナンスが容易になります。
<template>
<div>
<h2>Child Component</h2>
<nav>
<!-- Child ComponentからAboutへのリンク -->
<router-link :to="{ name: 'about' }">Go to About</router-link>
</nav>
</div>
</template>
Vue Router
Vue Routerは、Vue.jsアプリケーションにルーティング機能を追加するための公式ライブラリです。このライブラリをインポートすることで、ルーター機能を特定のファイルに付与できます。一般的には、router/index.jsにVue Routerをインポートし、このファイルは最終的にmain.jsにインポートされます。こうすることで、ルーターインスタンスをVueアプリケーションに適用できます。
router/index.js
は、main.jsにインポートされることを前提としたファイルです。そのため、ルーティング設定を直接main.jsに書くことも可能ですが、その場合、main.jsのコードが長くなり、可読性が低下するため、これを避けるためにルーティング設定を別のファイル(通常はrouter/index.js)に記述することで、コードの可読性を向上させています
createRouter
Vue Router においてルーティングの設定を行うための関数です。この関数を使うことで、アプリケーション内でのページ遷移を管理するためのルーターインスタンスを作成できます
createWebHistory
createWebHistory
は、Vue Router においてルーティングの履歴を管理するための機能です。インポートしない場合、URL の一部に「ハッシュ(#)」が含まれます。例えば、http://localhost:8080/#/ のような形式です。この場合、検索エンジンのSEOに悪影響を及ぼす可能性があります。
逆にcreateWebHashHistory
の場合はURL の一部に「ハッシュ(#)」を付与するため、サーバーの設定が難しい場合や、古いブラウザの対応が必要な場合に有効です
component: () => import( '../URL')
通常、Vueコンポーネントはファイルの最初でimportして一度に読み込むのが一般的ですが、特定のURLにアクセスがあった際に初めてそのコンポーネントを読み込みを実施します。そうすることで、アプリケーション全体の効率を高め、初期のロード時間を短縮できます
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
}
]