下記のようなコードでVue.jsからaxiosでPOSTのメソッドを処理しているのですが、なぜか2回POSTが走ってしまうという謎現象が発生しています。
<template>
<form @submit.prevent="send">
<!-- フォーム部分略 -->
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button type="submit" class="btn btn-primary"><i class="fas fa-fw fa-paper-plane" aria-hidden="true"></i>送信</button>
</div>
</div>
</form>
</template>
<script>
import axios from 'axios'
export default {
//コンポーネントや他のプロパティ略
data() {
return {
//他のデータ略
senddata: {}
}
},
methods: {
send() {
axios.post(URI + 'post/post', this.senddata) //senddataは送信ボタン押下時にはセットされている
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
}
}
</script>
試したこと
- [x]
@submit.prevent="send"
を@submit.stop.prevent="send"
に変更し、イベントの伝搬を停止するようにした - [x] 上記のイベント伝搬停止とは別に
send
メソッドの中でevent.preventDefault()
、event.stopPropagation()
を追加した- [x]
send
メソッドの最後にreturn false
を追記。コールバックの中にもreturn false
追記
- [x]
- [x] 親コンポーネントでもaxiosを読み込んでいる(同じ
import axios from 'axios'
文)なので、import axiosPost from 'axios'
としてインスタンス名を変更した - [x] 送信ボタンを
type="submit"
からtype="button"
にして@click="send"
で処理を実行するように変更- [x]
type="submit"
からtype="button"
にし、さらにform
タグをdiv
タグに変えて@submit.prevent="send"
を削除、代わりに@click="send"
を追加
- [x]
結果
上記の試した内容全て効果なし。何が原因なのか……。
気付いたこと
send
内にconsole.log('method in')
など適当に出力させると、Chrome開発者ツールのConsoleには1度しか出力されていない。
また、レスポンスも1度しか出力されていない(エラーのcatch
には入っていなさそう)ので、send
メソッドが重複してコールされているわけではなさそう。
よくよく見たら、Headerに上記画像のような違いが見られました。
対処
検索したところ、URLSearchParams
を使う方法がヒットしました。JSON形式ではなく従来のPOST形式でのデータ送信になってしまいイマイチ乗る気がしませんが、試したところ上手く行って本来の想定であるPOSTが1回だけになったので、とりあえずはこれで行こうかと思います。
コードは下記のように修正。
<template>
<form @submit.prevent="send">
<!-- フォーム部分略 -->
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button type="submit" class="btn btn-primary"><i class="fas fa-fw fa-paper-plane" aria-hidden="true"></i>送信</button>
</div>
</div>
</form>
</template>
<script>
import axios from 'axios'
export default {
//コンポーネントや他のプロパティ略
data() {
return {
//他のデータ略
senddata: null
}
},
methods: {
send() {
axios.post(URI + 'post/post', this.senddata) //送信ボタン押下する時にはsubmitPrepareで値がセットされている
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
},
submitPrepare() {
const params = new URLSearchParams() //パラメータのインスタンス生成
for(let key in this.formdata) {
params.append(key, this.formdata[key].data) //キーに値を追加
this.senddata = params //値セット
}
}
}
}
</script>
参考
- axiosでPOSTでRequestしているつもりがOPTIONSで送信している ? Qiita
- 【PHP】JSONデータのPOST受け取りで application/x-www-form-urlencoded とapplication/json の両方に対応 ? Qiita
- ブラウザの時にaxiosのPOSTの値が送信されない?そんなことはない ? Qiita
- backboneからのajaxがpayloadでPHPの$_POSTで取得できない ? バカンス駆動開発
追記 (2020/10/13)
今更と言えば今更ですが、この挙動は preflight request が飛んでいる挙動ですね、これ。
preflight request の挙動についてはCORS の挙動の観察と preflight request の検証の記事で追跡しました。