Vue.js で調べたいことがあったのでメモがてら。
やりたいこと
Vue.jsで、ユーザーの操作に合わせてデータの増減や表示の切り替えをしたい。
テストシナリオとして、以下の3つを試してみる
- アクセスカウンタ
- ユーザーの操作で数字が増減する
- 表示切り替え
- ユーザーの操作で配列内のデータを切り替えて表示
- REST API のデータの表示切り替え
- REST API経由で取得したデータを切り替えて表示
アクセスカウンタの実装
Vue.js でアクセスカウンタを実装する方法は、公式ドキュメント「イベントハンドリング」に書いている。
v-on ディレクティブを使うことで、DOM イベントの購読、イベント発火時の JavaScript の実行を行う。
以下は、簡単なアクセスカウンタの例。
こちらの記事を参考にしました。 元記事では Node.js を利用していますが、今回は1枚のhtmlに書き直しています。
Vue.js はCDNから読み込んでいます。
Vue.js のインスタンス「vm」を生成。vmに変数「count」を初期値0として定義。countはリアクティブな状態にして、v-on ディレクティブで変数countに対し増減を行う。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Vue.js でカウンター練習</title>
<meta charset="utf-8">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<h1>Vue.js でカウンターの練習</h1>
<div id="counter">
<div>{{count}}</div>
<button v-on:click="decrement">-1</button>
<button v-on:click="increment">+1</button>
</div>
<script>
"use strict";
const vm = new Vue({
el: '#counter',
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
},
decrement() {
this.count--
}
}
});
</script>
</body>
</html>
実際に動くサンプルはこちら。
https://codepen.io/TakeshiNickOsanai/pen/jXwrWL
配列の中身をVue.js で切り替える
さきほどのアクセスカウンタを少しアレンジ。
- 配列に格納されている文字列を「次へ」「前へ」のボタンクリックで切り替えながら表示する。
- 配列内のデータを、増減する変数「count」をキーとして取得、レンダリングする。
アクセスカウンタでは、無限に数字を増減できた。
今回のシナリオでは、配列に格納されたデータを上限として、表示のコントロールをする必要がある。そこで配列の中身をlengthで取得し、数字に上限を設けた。
同様に、0以下にはデクリメントできないように修正した。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Vue.js で配列の中身を切り替えながら表示する練習</title>
<meta charset="utf-8">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<h1>Vue.js で配列の中身を切り替えながら表示</h1>
<div id="counter">
<div>{{arr[count]}}</div>
<button v-on:click="decrement">前へ</button>
<button v-on:click="increment">次へ</button>
</div>
<script>
"use strict";
const vm = new Vue({
el: '#counter',
data () {
return {
arr : ['apple', 'orange', 'strawberry'],
count: 0
}
},
methods: {
increment(){
if (this.count < this.arr.length -1 ){
this.count++;
}
},
decrement() {
if(this.count > 0) {
this.count--
}
}
}
});
</script>
</body>
</html>
実際に動くサンプルはこちら
上記の例では、Vueインスタンス内のdataオブジェクトにあらかじめ配列を格納した。
下記は、先に中身が空のオブジェクト「arr」を生成。リアクティブな状態で待受を行い、あとで配列を格納する書き方。動作は上記と同じ。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Vue.js で配列の中身を切り替えながら表示する練習</title>
<meta charset="utf-8">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<h1>Vue.js で配列の中身を切り替えながら表示</h1>
<div id="counter">
<div>{{arr[count]}}</div>
<button v-on:click="decrement">前へ</button>
<button v-on:click="increment">次へ</button>
</div>
<script>
"use strict";
const vm = new Vue({
el: '#counter',
data() {
return {
arr: '',
count: 0,
}
},
methods: {
increment() {
if (this.count < this.arr.length - 1) {
this.count++;
}
},
decrement() {
if (this.count > 0) {
this.count--
}
}
}
});
// Vueインスタンス生成後、配列「arr」にデータを追加
vm.arr = ['apple', 'orange', 'strawberry'];
</script>
</body>
</html>
実際に動くサンプルはこちら
REST APIからデータを取得し、切り替えながら表示を行う
もう少しアレンジを加えて、以下のようなことをやってみる。
- REST APIからJSONデータを取得
- 今回は作家「古川日出男」さんの書籍データを、Google Books APIから取得する
- 書籍データのJSONから、書籍名を配列に格納
- ユーザーの操作で、書籍名を切り替えながら表示
Google Books API から取得したJSONデータをループ処理して、タイトルだけをVMインスタンス内の配列「arr」にPUSHしていく。あとは配列のサンプルと同じ。
API経由でデータを取得してからレンダリングを行うために、Promise で非同期処理を行う。
REST APIとの通信は、axiosを使いました。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Vue.js でREST APIから取得したデータの切り替え練習</title>
<meta charset="utf-8">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<h1>古川日出男の著作一覧</h1>
<div id="counter">
<div>{{arr[count]}}</div>
<button v-on:click="decrement">前へ</button>
<button v-on:click="increment">次へ</button>
</div>
<script>
"use strict";
const list = axios('https://www.googleapis.com/books/v1/volumes?q=%E5%8F%A4%E5%B7%9D%E6%97%A5%E5%87%BA%E7%94%B7');
const vm = new Vue({
el: '#counter',
data() {
return {
arr: [],
count: 0,
}
},
methods: {
increment() {
if (this.count < this.arr.length - 1) {
this.count++;
}
},
decrement() {
if (this.count > 0) {
this.count--
}
}
}
});
Promise.resolve(list).then(function(response) {
for (let i in response.data.items) {
vm.arr.push(response.data.items[i].volumeInfo.title);
}
});
</script>
</body>
</html>
動作するサンプルはこちら