質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

2回答

1752閲覧

Vue.js(axios)のAPIアクセス時のトークンを変数にしたい

EjiOsa

総合スコア18

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2019/01/30 00:31

編集2019/01/31 08:12

#やっていること
LaravelをAPIサーバーとして使用、vue(axios)でアクセスして画面表示させるアプリケーションを作成中です。
Laravelでの認証は標準装備のtokenを利用したもので、下記のようにハードコードすればvueも表示できます。

vue

1let axios = require('axios').create({ 2 baseURL: ApiUrl, 3 headers: { 4 'Accept': 'application/json', 5 'Authorization': 'Bearer '+'uGI09ICALLdclOBvsbdthstXKodnfavpHMmRCi4KhALJShbN1s8KmTdi', 6 }, 7 responseType: 'json' 8 });

#実現させたい状態
'Bearer '+'uGI09ICALLdclOBvsbdthstXKodnfavpHMmRCi4KhALJShbN0s8KmTdi'

'Bearer '+tokenData

とトークンを変数にしたい。

#試したこと
tokenDataは親コンポーネントから送られてきているのでpropsにあります。(vueのdevツールやtemplateに{{ tokenData }}で文字列は表示されるので変数には代入されているようです。)
vueのドキュメントにはpropsからdataやcomputedに入れてから使用するようにとあったので、dataやcomputedを介しての使用も試しました。

'Bearer '+tokenData, //NG
'Bearer '.concat(tokenData), //NG
'Bearer '.concat(this.tokenData), //NG

#教えて欲しいこと
そもそも実現させたいことが間違っているのか、JS構文のミスなのか。
いずれはvuexも使用をするつもりですが、今は動きの確認中なのでvuexは使用せずpropsでの動作を試みています。
ヒントだけでも教えていただけると助かります。

#追記
実際に動かしているコンポーネントの全体像になります。
以下のハードコード時はvueDevツール内のpropsとcomputedには文字列が入っております。

vue

1<template> 2 <div> 3 <div class="head"> 4 <h2>User Registration</h2> 5 </div> 6 <ul class="side-bar-list"> 7 <SideBar 8 v-for="user in users" 9 :key="user.id" 10 :userData="user" 11 @userEdit="userEdit" 12 ></SideBar> 13 </ul> 14 </div> 15</template> 16 17<script> 18 import SideBar from './registration_components/SideBar'; 19 20 const ApiUrl = 'http://localhost/*******/*******/public/api/items'; 21//==================================================================== 22//ここの部分に問題があると考えています。 23 24 var headers = { 25 'Accept': 'application/json', 26 // 'Authorization': 'Bearer '+'uGI09ICALLdclOBe8UtTvykugiydnoJkcc6pHMmRCi4KhALJShbN2s8KmTdi',//このようにハードコードするとエラーがありません。 27 'Authorization': 'Bearer '.concat(this.tokenNo), 28 }; 29 30//==================================================================== 31 let axios = require('axios').create({ 32 baseURL: ApiUrl, 33 headers: headers, 34 responseType: 'json' 35 }); 36 37export default { 38 name: 'UserControl', 39 props:{ 40 tokenData: { 41 type: String, 42 // required: true 43 } 44 }, 45 components: { 46 SideBar 47 }, 48 computed:{ 49 tokenNo() { 50 return this.tokenData 51 } 52 }, 53 data () { 54 return { 55 users: null, 56 editUser: { 57 first_name: '', 58 family_name: '', 59 age: '', 60 email: '', 61 password: '', 62 edit: false 63 } 64 }; 65 }, 66 mounted () { 67 axios.get(ApiUrl) 68 .then(response => (this.users = response.data)); 69 }, 70 methods: { 71 // edit method 72 clearEdit () { 73 this.editUser = { 74 first_name: '', 75 family_name: '', 76 age:'', 77 email: '', 78 password: '', 79 edit: false 80 }; 81 }, 82 // SideBar method 83 userEdit (selectUserID) { // ユーザー編集のONとOFF 84 let selectEditUser = this.users.findIndex(({ id }) => id === selectUserID);// IDから編集を選択されたユーザー取得 85 this.releaseEdit(selectEditUser); 86 this.users[selectEditUser].edit = !this.users[selectEditUser].edit; 87 this.setCurrentUser(); 88 this.$forceUpdate(); 89 }, 90 releaseEdit (userIndex) { // 選択したユーザー以外が編集中だった場合に解除 91 let editTrueIndex = this.users.findIndex(({ edit }) => edit === true);// 編集中のユーザーインデックスを取得 92 if (editTrueIndex > -1) { // indexで取得のためindexが有効かチェック 93 if (this.users[editTrueIndex].edit !== this.users[userIndex].edit) { // 編集中のユーザーと選択したユーザーが違う場合に削除発火 94 this.users[editTrueIndex].edit = false; 95 } 96 } 97 }, 98 setCurrentUser () { // 編集ONになった際に右の編集画面に反映させるメソッド 99 let editTrueIndex = this.users.findIndex(({ edit }) => edit === true); 100 if (editTrueIndex > -1) { 101 this.editUser = this.users[editTrueIndex]; 102 } else { 103 this.refresh();//編集を更新しない場合はデータベースを再取得 104 this.clearEdit();//右側の記入欄をクリア 105 } 106 }, 107 //Api method 108 async update (data) {//ユーザー情報の更新 109 await axios.put(ApiUrl+'/'+data.id, data) 110 .then( 111 alert('user edit ok') 112 ) 113 .catch(function (err) { 114 alert(err) 115 }); 116 this.refresh() 117 }, 118 async addUser () {//Userの追加 119 await axios.post(ApiUrl, this.editUser) 120 .then( 121 alert('user add ok') 122 ) 123 .catch(function (err) { 124 alert(err); 125 }); 126 this.refresh()//thenの中に書いて不安定になってたけど、ここにして安定した。 127 }, 128 async softDelete (id) {//Userの論理削除、Deleted_atにTimeStamp入力 129 await axios.delete(ApiUrl+'/'+id) 130 .then( 131 alert('user softDeleted ok') 132 ) 133 .catch(function (err) { 134 alert(err) 135 }); 136 this.refresh() 137 }, 138 refresh (){//Api処理後の再表示 139 axios.get(ApiUrl) 140 .then(response => ( 141 this.users = response.data 142 )) 143 .catch(err => ( 144 alert(err) 145 )); 146 }, 147 // Registration method 148 add () { 149 if (this.users.find(editId => editId.id === this.editUser.id)) { //users内にeditUserのidが存在する=>更新の場合 150 if (confirm('ユーザー情報を更新しますか?')) { 151 //↑ var result = confirm('ユーザー情報を更新しますか?')をそのまま代入している。 152 var editTrueIndex = this.users.findIndex(({edit}) => edit === true);// 編集中のインデックス取得 153 this.users[editTrueIndex].edit = !this.users[editTrueIndex].edit; // 編集ボタンを解除 154 this.update(this.users[editTrueIndex]); 155 this.clearEdit(); 156 } 157 } else { // users内にeditUserのidが存在しない=>追加の場合 158 if (confirm('ユーザーを追加しますか?')) { 159 this.addUser(); 160 this.clearEdit(); 161 } 162 } 163 }, 164 del () { 165 if (confirm('ユーザーを削除しますか?')) {//user削除 166 var editTrueIndex = this.users.findIndex(({edit}) => edit === true); 167 this.softDelete(this.users[editTrueIndex].id); 168 this.clearEdit(); 169 this.refresh(); 170 } 171 }, 172 } 173}; 174</script> 175 176<style scoped lang="scss"> 177 178</style>

methods内でもaxiosは使用していますが、動的な部分ですので初期表示のmountedがメインのエラー個所と考えています。
#エラーコード

vue

1'Authorization': 'Bearer '.concat(this.tokenNo)

上記、使用時のエラーコードは以下になります。

app.js:2947 Uncaught TypeError: Cannot read property 'tokenNo' of undefined

恥ずかしい話、今回の質問後にエラーを確認しましたがundefinedでした。
しかし、なぜundefinedになってしまっているのかわかりません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

親コンポーネントがトークンを取得する前にAPI呼んでるのでは・・・?
'Bearer '.concat(this.tokenData)でダメなのから推測すると、this.tokenDataが空の状態でAPI呼んでると思います。
ChromeのデベロッパーツールのNetworkタブをXHRでフィルタリングして見てリクエストがどうなってるか見てみると良いですよ。

追記

export default {...} の外側でthis.tokenNoを参照してるので、未定義の変数を参照してエラーになってます。
下記のような感じにすると良いと思います。

vue

1<script> 2import SideBar from './registration_components/SideBar'; 3import axios from 'axios'; 4 5const ApiUrl = 'http://localhost/*******/*******/public/api/items'; 6 7export default { 8 // 中略 9 10 computed: { 11 client() { 12 return axios.create({ 13 baseURL: ApiUrl, 14 headers: { 15 'Accept': 'application/json', 16 'Authorization': `Bearer ${this.tokenData}`, 17 }, 18 responseType: 'json' 19 }); 20 } 21 }, 22 23 methods: { 24 async update (data) {//ユーザー情報の更新 25 await this.client.put(`/${data.id}`, data) 26 .then( 27 alert('user edit ok') 28 ) 29 .catch(function (err) { 30 alert(err) 31 }); 32 this.refresh() 33 }, 34 }, 35 36 // 中略 37} 38</script>

投稿2019/01/30 05:21

編集2019/01/31 08:49
yhg

総合スコア2161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

EjiOsa

2019/01/30 20:19

Networkタブ→XHRでリクエストを確認しました。 当然ですがハードコード時は'Authorization'の項目もあり、エラーも出ていませんでした。 .concatや+で文字列結合すると、エラーでリクエスト自体も無くなります。vueコンポーネントの表示もなくなっています。 また、vueのdevツールやtemplateに{{ tokenData }}で文字列は表示されるので変数に文字列は入っていると考えていたので、今回のエラーの原因は文字列結合の構文エラーかと考えていました。 文字列結合時にthis.tokenDataが空になってしまうことがあるのでしょうか? また、空の文字列を渡していたら'Authorization'の項目は残ってStatusCodeも400番台になると考えていましたが、その認識から間違っているでしょうか。 よろしくお願いいたします。
yhg

2019/01/31 04:19

EjiOsaさんの認識で正しいです。 私は文字列結合時に空になるのではなく、文字列結合の直前の this.tokenData が空の状態なのではないかと考えていました。 ですが、エラーでリクエスト自体が発生しないのなら、空の状態でも結合自体は成功するはずなので別の問題っぽいですね。 コンポーネント全体のコードやエラー内容とか貼っていただければ、具体的な原因が分かるかもしれません。
EjiOsa

2019/01/31 08:17

返信ありがとうございます。 本文にコンポーネントの全体やエラーコードを追加しました。 流れとして、Laravelのapi_tokenはblade.phpでコンポーネント呼び出し時にAuth::user()->api_tokenで取得、一つコンポーネントを挟んでから今回のコンポーネントになります。バケツリレーになっているので今後はvuexも必要かと考えていますが、このようなエラーが解決できなくてはvuexも理解できないと考えてvuexは使用せずに調査しています。
guest

0

ベストアンサー

headersを変数に入れてaxios呼び出し時にセットしてみてはどうでしょう?

vue

1let headers = { 2 'Accept': 'application/json', 3 'Authorization': 'Bearer '+ tokenData, 4} 5axios.get('/users', headers) 6axios.post('users', body, headers)

のような形でheadersをaxiosに設定できると思います。

投稿2019/01/30 00:39

y-ogura

総合スコア23

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

EjiOsa

2019/01/30 20:20 編集

回答のようにaxios呼び出し時にheadersを引数に入れる方法をとりましたが、エラーで全vueコンポーネントが表示されませんでした。 headersを入れずにURLのみの場合は動くので、headersを呼び出し時に入れる方法に何か不手際があると考えてます。 再度、誤字脱字からチェックをしたいと思います。何かヒントがあればよろしくお願いいたいます。
y-ogura

2019/01/31 02:09 編集

axios呼び出し時のコードと、エラーの内容も合わせて教えてもらえますか? ちなみに私はいつもvue-axiosを使用して~/pluginsにaxiosの初期設定ファイルを置いています。 ``` import Vue from 'vue' import axios from 'axios' import VueAxios from 'vue-axios' const instance = axios.create({ // ここに初期設定項目 }) Vue.use(VueAxios, instance) ```
EjiOsa

2019/01/31 08:25 編集

返信ありがとうございます。 本文にコンポーネント全体とエラーコードを追加しました。 現在の開発環境はvue独立使用ではなく、Laravel内のvueとaxiosの使用になっているので初期設定はbootstrap.jsに記載されています。 もしかしたら、このbootstrap.jsの影響があるのでしょうか? その方向性からもチェックしてみたいと思います。 現時点ではbootstrap.jsの内容は何も触っていません。 また、会話が噛み合ってなかったら申し訳ありません。
y-ogura

2019/01/31 09:32

おそらくですが、export defaultの外でthis.tokenNoを使用していることが、原因だと思われます。 propsでtokenDataを取得しているのであれば例えば ``` data () { return { // 他のdataは省略してます headers: { 'Accept': 'application/json', 'Authorization': 'Bearer '+ this.tokenData } } } ``` としてしまって ``` let axios = require('axios').create({ baseURL: ApiUrl, responseType: 'json' }); ``` でaxiosのインスタンスを作成 APIを叩くときに await axios.post(ApiUrl, this.editUser, this.headers) と書いてみてはどうでしょう?
EjiOsa

2019/02/01 05:08

data()内で宣言することでheadersは使用可能となりました。 ですが、axiosの第2引数には代入できず。 axios.defaults.headers['Authorization'] = 'Bearer '+this.tokenData; といった一文を挟んでエラーなく実行しています。 そのため結果的には全て解決には至っておりませんが、export defaultの内外での変数の使用が良くなかったのはわかったので、今回の質問では解決にさせていただきました。 export defaultについてと、axiosについて学習を続けて理解を深めたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問