Vue3とaxiosで外部サイトにアクセス
こんにちは、あっくんです。10月に入りましたが、日々30℃近くでなかなか気温が下がらないですね。僕は就活と勉強に挑戦中ですが、なかなかうまく行かないですね。自己管理がうまく行っていないです。特に睡眠がコントロールできないくらい眠っていますね。人は仕事や、職業訓練など人との約束は守りますが自分の約束は自分に甘えて守れないような気がします。だからこそ、自分を律してここから踏ん張ってやってみます。今回はaxiosで外部サイトにアクセスしていきましょう。
「データ」の扱いを考えよう
巨大データをどう扱う?
巨大データを利用する場合は外部のサイトにアクセスして必要なデータを取り出してくる、あるいはデータベースを利用してデータを処理をするといったやり方があります。Vue.jsの標準な機能ではできないことがあった場合はVue.jsにパッケージを追加して機能拡張することができます。
axiosって?
axiosはHTTP通信のための機能を提供するパッケージです。HTTP通信とは、「Webサービスにアクセスして必要な情報をやり取りする機能」のことです。これは、JavaScriptの一般的なライブラリです。
axiosのインストール
axiosをインストールしていきましょう。axios_appプロジェクトをViteで作ってやっていきましょう。
開発するディレクトリでターミナルに↓のように記述してaxios_appを作って、npmをインストールします。
npm init vite-app axios_app
cd axios_app
npm install
npm install axios
↑npm installでaxiosをインストールします。
axiosでサイトにアクセスするには?
axiosでサイトにアクセスするには、axiosのライブラリをインポートします。
import axios from 'axios'
axiosというオブジェクトにaxiosの機能が組み込まれます。
getでデータを得る
指定したアドレスにアクセスしてデータを受け取る処理は↓のように行います。
変数 = await axios.get(アドレス)
axiosの「get」というメソッドを使います。引数にアクセスするアドレスをしていすれば、そこにアクセスして結果となるオブジェクトを返します。データは、返されたオブジェクトの「data」というプロパティに保管されています。getの戻値を変数で受け取り、そこからdataを取り出します。
同期処理と非同期処理
同期処理は1つプログラムを実行してはそれが完了し、次を実行してはそれが完了し…ということを繰り返していきます。コンピュータの処理はなにかの処理を実行し完了するという作業の積み重ねです。
非同期処理というのは、「同期しないで実行できる処理」です。処理を実行したら、「完了する前に次に進む」というものです。時間がかかる処理があると、同期処理の場合はプログラムが完了するまで長い時間かかるようになります。そこで、時間のかかる処理部分を「とりあえずこれをやっておくから先に進んで」というように時間のかかる処理はバックグラウンドで他の処理と並行して進められます。
awaitとasync
awaitというのは、非同期処理を利用する際に用いられるものです。これは非同期処理を同期処理的に実行するためのものです。本来非同期で実行される処理を処理がおわるまで待って次に進むようにするのです。↓のように記述します。
async 関数(引数{
await 非同期処理
}
Code language: JavaScript (javascript)
awaitを利用する場合は、それが入っている関数の冒頭に「async」というキーワードを付けておく必要があります。
axios.getも非同期処理です。しかし、awaitを付けて呼び出すことで、指定したアドレスにアクセスし、その結果を受け取ることができます。つまり、非同期なのに、普通の同期処理と同じ感覚で扱えるようになります。
テキストファイルを表示する
実際にaxios.getによるデータの取得をやってみましょう。axios_appにテキストファイルを用意してこれをaxiosで読み込ませてみましょう。axios_app内のpublicというフォルダに「data.txt」という名前でファイルを作成しましょう。そして、簡単なテキストを記述しておきましょう。
HelloWorld.vueを修正する
axiosの機能を使ってみましょう。
App.vueとHelloWorld.vueのコンポーネントを修正して動作を確認します。「components」フォルダ内の「HelloWorld.vue」を編集しましょう。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>axios</title>
<!-- CSS only -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
crossorigin="anonymous"
/>
<!-- JavaScript Bundle with Popper -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
crossorigin="anonymous"
></script>
</head>
<body>
<h1 class="bg-secondary text-white h4 p-3">Vue3 axios</h1>
<div class="container">
<div id="app"></div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
App.vue
<template>
<div id="app">
<HelloWorld />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld,
},
};
</script>
Code language: HTML, XML (xml)
HelloWorld.vue
<template>
<section class="alert alert-primary">
<h1>{{ data.title }}</h1>
<p>{{ data.message }}</p>
<textarea v-model="data.mydata" rows="5" class="form-control"></textarea>
</section>
</template>
<script>
import axios from "axios";
import { reactive, onMounted } from "vue";
const url = "/data.txt";
export default {
setup(props) {
const data = reactive({
title: "Axios",
message: "This is axios sample.",
mydata: "",
});
const getData = async () => {
let result = await axios.get(url);
data.mydata = result.data;
};
onMounted(() => {
getData();
});
return { data, getData };
},
};
</script>
Code language: HTML, XML (xml)
↑http://localhost:3000/axiosにアクセスすると、「public」フォルダにあるdata.txtの中身を読み込んで表示します。
「public」フォルダについて
「public」フォルダは静的ファイル(イメージファイルなど、ファイルをそのまま表示するだけのもの)を扱うためのフォルダで、個々にあるファイルはそのままファイル名を指定してアクセスすることができます。例えば、data.txtファイルはhttp://localhost:3000/data.txtにアクセスするとその内容が表示されます。
↑http://localhost:3000/data.txtにアクセスするとdata.txtの内容がそのまま表示されます。
コンポーネントをチェックする
作成したHelloWorld.vueのテンプレート部分を見ていきましょう。
<textarea v-model="data.mydata" rows="5" class="form-control"></textarea>
今回は、v-modelを使って、data.mydataが表示されています。
スクリプトの処理
import axios from 'axios'
import {reactive, onMounted} from 'vue'
Code language: JavaScript (javascript)
これでaxios変数にaxiosのオブジェクトが読み込まれています。
const url = "/data.txt"
アドレスは同じサイト内にアクセスするなら、このようにドメイン名の部分を省略してパスの部分だけ記述して大丈夫です。
setupの用意
setup(props) {
const data = reactive({
title: "Axios",
message: "This is axios sample.",
mydata: "",
})
const getData = async () => {
let result = await axios.get(url);
data.mydata = result.data;
}
onMounted(() => {
getData();
})
return { data, getData };
},
Code language: JavaScript (javascript)
ここでは、title,message,mydataといった値が用意されています。mydataはテキストエリアのv-modelで連携させています。
getDataについて
基本の書き方
async function() {
……..非同期処
}
Code language: JavaScript (javascript)
アロー関数の場合
async ()=> {
………非同期処理
}
Code language: JavaScript (javascript)
getDataではaxios利用の処理を用意してます。
const getData = async()=> {
let result = await axios.get(url)
data.mydata = result.data
}
Code language: JavaScript (javascript)
async()=> {…….}というようにして関数を定義してあります。これで、getDataを呼び出すとawait axios.getで指定のアドレスからデータを取得し、それをdata.mydataに設定します。dataはリアクティブになっていますからmydataを変更すれば、それがv-modelに設定されているテキストエリアの表示も更新されます。
onMountedについて
onMounted(()=> {
getData()
})
Code language: JavaScript (javascript)
onMountedは、コンポーネントがマウントされた際に呼び出されるイベントフックです。
axiosを非同期処理で実行するには?
axios.get(アドレス.then((引数)=>{
……..完了後の処理後の処理
})
Code language: JavaScript (javascript)
getはawaitをつけずに呼び戻すと、「Promise」というオブジェクトを返します。このPromiseは「非同期処理が終わった後に実行する処理の予約」みたいなものです。このPromiseオブジェクトの「then」というメソッドを呼び出し、その引数に関数を用意しておくと、このPromiseを返した非同期処理がすべて完了したあとでその関数が実行されるようになります。
getDataを修正する
先程のaxiosを使った処理を非同期で実行するように修正してみます。HelloWorld.vueのgetDataを書き換えます。
HelloWorld.vue
↑先程と全く同じようにdata.txtにアクセスして表示します。
axios.get(url).then((result)=> {……}
getの後にthenを呼び出して、底に関数を用意する。
data.mydata = result.data
関数の引数に渡されるresultオブジェクトの「data」というプロパティに取得したテキストデータが保管されています。これを、mydataに設定することで、テキストエリアに表示されるようになります。
この「thenを使った非同期処理」はaxiosに限らず、JavaScriptの多くの非同期処理で使われるやり方です。
・JOSNデータのサイトを活用しよう
外部のサイトにアクセスしてデータを読み込んでいきましょう。ここでは、JSONPlaceholderというWebサービスを利用していきましょう。これは、JSONのダミーデータを公開しているサイトです。
https://jsonplaceholder.typicode.com/
ここでは、様々な形でJSONデータを配布しています。
用意される全データを全部取得する
https://jsonplaceholder.typicode.com/posts
指定のID番号のデータを取得する
https://jsonplaceholder.typicode.com/posts/番号
サイトからデータを取得する
JOSNPlaceholderサイトからデータを取得して表示していきましょう。ID = 1のデータを取り出して表示していきましょう。
HelloWorld.vueを書き換えていきましょう。
HelloWorld.vue
<template>
<section class="alert alert-primary">
<h1>{{ data.title }}</h1>
<p>{{ data.message }}</p>
<table class="table table-light table-striped">
<tbody class="text-start">
<tr>
<th style="width: 200px">User ID</th>
<td>{{ data.json_data ? data.json_data.userId : "-" }}</td>
</tr>
<tr>
<th>ID</th>
<td>{{ data.json_data ? data.json_data.id : "-" }}</td>
</tr>
<tr>
<th>Title</th>
<td>{{ data.json_data ? data.json_data.title : "-" }}</td>
</tr>
<tr>
<th>Body</th>
<td>{{ data.json_data ? data.json_data.body : "-" }}</td>
</tr>
</tbody>
</table>
</section>
</template>
<script>
import axios from "axios";
import { reactive, onMounted } from "vue";
let url = "https://jsonplaceholder.typicode.com/posts/";
export default {
setup(props) {
const data = reactive({
title: "Axios",
message: "This is axios sample.",
json_data: null,
});
const getData = () => {
let id = 1; //id番号
axios.get(url + id).then((result) => {
console.log(result.data);
data.json_data = result.data;
});
};
onMounted(() => {
getData();
});
return { data, getData };
},
};
</script>
Code language: HTML, XML (xml)
↑アクセスすると、JSONPlaceholderからID = 1のデータを表示します。
JSONデータの扱い
const data = reactive({
title: "Axios",
message: "This is axios sample.",
json_data: null,
});
Code language: JavaScript (javascript)
json_dataというのが、取得したJOSNデータを保管して置くためのものです。 値は初期値でnullにしています。
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
Code language: JavaScript (javascript)
JSONPlaceholderの/post/1にアクセスしています。JSON形式になっていますが、送られてくるのは、ただのテキストです。
Code language: PHP (php)(result) => { data.json_data = result.data; }
getで受け取った結果からdataの値を取り出し、json_dataに設定しています。
{{ data.json_data ? data.json_data.userId : "-" }}
この段階でjson_dataはJavaScriptのオブジェクトになっています。json_dataは初期値はnull担っています。axiosで値を得て初めて、オブジェクトになります。axiosでは、getで受け取ったデータの形式がJSONだと、自動的にオブジェクトに変換して渡してくれます。
入力したIDのデータを表示する。
今度はmethodsにaxiosの処理を用意し、ボタンクリックで呼び出すサンプルを作っていきましょう。JSONPlaceholderをたうかって、 ID番号を入力するとそのデータを取り出し表示させてみましょう。
HelloWorld.vue
<template>
<section class="alert alert-primary">
<h1>{{ data.title }}</h1>
<p>{{ data.message }}</p>
<div class="form-group">
<input type="number" class="form-control" v-model="data.id" />
<button class="btn btn-primary m-2" @click="doClick">Click</button>
</div>
<table class="table table-light table-striped">
<tbody class="text-start">
<tr>
<th style="width: 200px">User ID</th>
<td>{{ data.json_data ? data.json_data.userId : "-" }}</td>
</tr>
<tr>
<th>ID</th>
<td>{{ data.json_data ? data.json_data.id : "-" }}</td>
</tr>
<tr>
<th>Title</th>
<td>{{ data.json_data ? data.json_data.title : "-" }}</td>
</tr>
<tr>
<th>Body</th>
<td>{{ data.json_data ? data.json_data.body : "-" }}</td>
</tr>
</tbody>
</table>
</section>
</template>
<script>
import axios from "axios";
import { reactive } from "vue";
let url = "https://jsonplaceholder.typicode.com/posts/";
export default {
setup(props) {
const data = reactive({
title: "Axios",
message: "This is axios sample.",
id: 0,
json_data: null,
});
const doClick = () => {
axios.get(url + data.id).then((result) => {
data.json_data = result.data;
});
};
return { data, doClick };
},
};
</script>
Code language: HTML, XML (xml)
↑入力フィールドに番号を入力しボタンをクリックすると、そのID番号のデータが表示されます。
doClickの処理
const doClick = () => {
axios.get(url + data.id).then((result) => {
data.json_data = result.data;
});
};
Code language: JavaScript (javascript)
入力された値はv-model=”data.id”により、this.idに保管されています。この値を取り出し、urlにつけてaxios.getにアクセスしています。そして、then内のアロー関数で、引数のresultからdataを取り出し、this.data.json_dataに設定しています。
エラー対策はどうする?
ネットワークアクセスを行う場合、「必ずアクセスが成功するとは限らない」ということです。アクセスしたアドレスがまちがっていたり、あるいはサーバーが停止していたり、データが存在しなかったり、さまざまなことが原因でエラーが発生します。こういう場合は、catchというメソッドを使います。
axios.get(アドレス).then(…….).catch((error)=>{…..エラー処理…..})
get.thenの後に更にメソッドチェーンを使ってcatchを記述します。thenと同じように、引数には関数を用意します。その関数の引数に、エラーの情報をまとめたオブジェクトが渡されます。
エラー対策を追加する
HelloWorld.vue
<template>
<section class="alert alert-primary">
<h1>{{ data.title }}</h1>
<p>{{ data.message }}</p>
<div class="form-group">
<input type="number" class="form-control" v-model="data.id" />
<button class="btn btn-primary m-2" @click="doClick">Click</button>
</div>
<table class="table table-light table-striped">
<tbody class="text-start">
<tr>
<th style="width: 200px">User ID</th>
<td>{{ data.json_data ? data.json_data.userId : "-" }}</td>
</tr>
<tr>
<th>ID</th>
<td>{{ data.json_data ? data.json_data.id : "-" }}</td>
</tr>
<tr>
<th>Title</th>
<td>{{ data.json_data ? data.json_data.title : "-" }}</td>
</tr>
<tr>
<th>Body</th>
<td>{{ data.json_data ? data.json_data.body : "-" }}</td>
</tr>
</tbody>
</table>
</section>
</template>
<script>
import axios from "axios";
import { reactive } from "vue";
let url = "https://jsonplaceholder.typicode.com/posts/";
export default {
setup(props) {
const data = reactive({
title: "Axios",
message: "This is axios sample.",
id: 0,
json_data: null,
});
const doClick = () => {
axios
.get(url + data.id)
.then((result) => {
data.json_data = result.data;
})
.catch((error) => {
data.message = "ERROR!";
data.json_data = null;
});
};
return { data, doClick };
},
};
</script>
Code language: HTML, XML (xml)
↑100より大きい数字を入力すると」ERROR!と表示されます。
データが見つからないとサーバーからHTTP404エラーというエラーコードが送られてきます。それによりcatchにジャンプして処理が実行されました。
ここまで読んでいただいてありがとうございます。
外部へのアクセスをaxiosというJavaScriptのライブラリを読み込んで実行しました。axiosと非同期処理の組み合わせで、ユーザーに負担をかけない処理を作ってみたいですね。
引き続きJavaScriptの基本もしっかりやっていきます。
掌田津耶乃さんのVue.js3超入門で勉強をしています。語りかけるような文章ですごいわかりやすいです。本当におすすめです。