JavaScript
vue.js

Vue.jsでGETとPOSTを実装する

More than 1 year has passed since last update.

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を行う

を参照のこと。


フォームのイメージ

vue.jsのフォームイメージ


具体的な実装方法


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で表示を変えるのが良い。

event-new.html

<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が成功したか否かを確認できる。

event_add.js

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")
}
},
}
})