Vue.jsにおけるGET・ POSTに関する情報がほとんどない(公式のREADMEくらい)ので、上手くいった例をまとめておく。
GET/POSTにはvue-resoureを用いた。
この辺の処理はAngularJSとよく似ているので、Vue.jsで調べるよりAngularJSで調べた方がヒントは得られるかもしれない。
#GET
イベントのリストをJSONで返してくれるAPIに対してGETをして、その結果を表示する例。
【GitHub】
##HTMLの実装
HTMLはシンプルで、js内でelに登録するidのhomeと、v-repeatでeventsの中の要素を取得して表示している。
<div id="home">
<h1>event list</h1>
<hr>
<div v-repeat="t : events">
{{$index}}
<h2>{{t.title}}</h2>
<p>{{t.description}}</p>
<p>{{t.date}}</p>
<p>{{t.location}}</p>
<hr>
</div>
<div>
</div>
</div>
それぞれの細かい説明は、3つだけ覚えてVue.jsでtodoアプリを作ってみるを参照。
##JSの実装
vue-resourceを使ってGETメソッドを行っている。
基本形は
this.$http.get(URL, function (data, status, request) {
//GETメソッドが成功した場合の処理
}).error(function (data, status, request) {
//GETメソッドが失敗した場合の処理
})
}
引数のdataはGETメソッドで取得されたデータが配列で、statusにはGETメソッドの結果が格納される。
- 取得したデータを呼び出したいときはdata[index]ようにして取り出す
- GETメソッドがうまくいったか確認したい場合はconsole.logでstatusを出力する
ようにしてやれば良い。
var app = new Vue({
//select html element
el: '#home',
//init data
data: {
events: [],
someData: [],
input: ""
},
//called when loaded
created: function(){
// GET request
var self = this
this.$http.get('http://example.com/forGET', function (data, status, request) {
for(var i = 0; i < data.length; i++){
this.events.push(data[i]);
}
}).error(function (data, status, request) {
// handle error
})
},
})
今回の例では、GETメソッドが成功した場合、dataからenventsリストにforループで受け取った値を格納している。
eventsの要素はv-repeatにリアルタイムに反映されるようにしているので、このforループ内においてその場で反映される。
#POST
Vue.jsでPOSTをする例として、イベントの作成フォームを作った。
- 入力に応じてリアルタイムでエラー情報を表示する(validation)
- 1回作成ボタンを押すまではエラー情報は出ない
- 作成ボタンを押すと、入力にエラーがなければ POSTする
ようになっている。
Vue.jsでのvalidationの方法については
Vue.jsでフォームのvalidationを行う
を参照のこと。
#具体的な実装方法
##event-new.htmlの実装
HTMLはVue.jsでフォームのvalidationを行うとほぼ一緒。
主にjsのaddEventメソッドが今回の主な実装。
HTMLの変更点としては
<ul id="errors" class="display-none">
の1行。
"1回作成ボタンを押すまではエラー情報は出ない"ようにするために、idを振ってdisplay-noneクラスを指定してる。
display-noneクラスは単にdisplay:noneにしているだけ。
###v-ifやv-showで表示/非表示をやらない理由
Vue.jsのv-ifやv-showでbooleanを渡して表示/非表示を切り替える方法もある。
しかし、表示した一瞬、エラー情報が表示されてしまう。
これはJSの処理がDOMツリーが構築より後に行われているため。
DOMツリーが構築されて表示された後に、v-ifやv-showが評価されて、falseなら非表示になる。
したがって、エラー情報が一瞬表示された後に消える。
最初から表示されないようにするためには、CSSでdisplay:noneにしておいて、のちにJSで表示を変えるのが良い。
<div id="app">
<form id="form" v-on="submit:addEvent">
<!-- それぞれに作ったvaidatorに通す -->
<p>title:<input v-model="newEvent.title | titleValidator" name='title' value=''></p>
<p>description:<textarea v-model="newEvent.description | descriptionValidator" name='description' value=''></textarea></p>
<p>date:<input v-model="newEvent.date | dateValidator" name='date' value=''></p>
<p>location:<input v-model="newEvent.location | locationValidator" name='location' value=''></p>
<input type="submit" value="イベントを作成">
</form>
<!-- error表示欄 -->
<ul id="errors" class="display-none">
<!-- you need to implement "display-none" class which is simply display nothing -->
<li v-show="!validation.title">タイトルが未入力です</li>
<li v-show="!validation.description">説明が未入力です</li>
<li v-show="!validation.date">日付が未入力です</li>
<li v-show="!validation.location">場所が未入力です</li>
</ul>
</div>
##event_add.jsの実装
validation周りはVue.jsでフォームのvalidationを行うとほぼ一緒。
###POSTの実装
POSTにはvue-resourceを使う。
// POST
this.$http.post('http://example.com/forPOST', this.newEvent, function (data, status, request) {
console.log("post success")
//status check
console.log(status)
}).error(function (data, status, request) {
console.log("post failed")
})
引数に
- URL
- POSTするパラメータ
- 成功した場合の処理
を渡し、エラーした場合の処理を追加する。
functionの引数のstatusの値を確認することで、POSTが成功したか否かを確認できる。
var add = new Vue({
// element to mount to
el: '#app',
// initial data
data: {
users: [],
newEvent: {
title: '',
description: '',
date: '',
location: ''
},
validation: {
title: false,
description: false,
date: false,
location: false
}
},
// validation 個別に作っているので、評価の仕方を変えられる
filters: {
titleValidator: {
write: function (val) {
this.validation.title = !!val
return val
}
},
descriptionValidator: {
write: function (val) {
this.validation.description = !!val
return val
}
},
dateValidator: {
write: function (val) {
this.validation.date = !!val
return val
}
},
locationValidator: {
write: function (val) {
this.validation.location = !!val
return val
}
}
},
// computed property for form validation state
computed: {
isValid: function () {
var valid = true
for (var key in this.validation) {
if (!this.validation[key]) {
valid = false
}
}
return valid
}
},
// methods
methods: {
addEvent: function (e) {
document.getElementById("errors").className = ""
e.preventDefault()
if (this.isValid) {
console.log("success")
console.log("title: " + this.newEvent.title)
console.log("description: " + this.newEvent.description)
console.log("date: " + this.newEvent.date)
console.log("location: " + this.newEvent.location)
// POST
this.$http.post('http://example.com/forPOST', this.newEvent, function (data, status, request) {
console.log("post success")
//status check
console.log(status)
}).error(function (data, status, request) {
console.log("post failed")
})
}else{
console.log("need edit")
}
},
}
})