各位大大好
小弟目前正在用NUXT開發網站碰到一個問題
因為目前所接的API都必須帶JWT
所以我把取得JWT Token 寫在 components>nav.vue 裡面
用的方法是打API 取得Token然後寫在localStorage裡面
我的想法是不管我到哪一頁都會先從localStorage取得JWT token然後打需要的api帶入token
然後我每一個頁面都有引入nav.vue這個組件所以每次都會將token重新寫入localStorage
寫完的確也有達到我想要的
但有個bug是如果我的localStorage還沒有token的話就會出現錯誤
原因是我先把畫面渲染出來了 可是渲染之前還沒有token 是渲染後才從nav.vue取得token
渲染頁面 > localStorage取不到token導致打其它API失敗 > 透過nav.vue取得token >頁面渲染完成(但有接API撈資料的地方都空白)
我必須要再重新整理一次(第一次已經透過nav.vue取得token)才能正常使用其它API
不曉得有沒有甚麼方法可以在頁面渲染出來前先取得 token然後寫在localStorage set裡面呢
打JWTAPI > localStorage set token > 渲染頁面 > 透過localStorage取得token打其它API >頁面渲染完成
想要做到這樣應該要怎麼寫比較好呢
還請各位前輩指點一下 謝謝
目前想到的方法是在我每個有打api的地方用setTimeout來執行
不曉得有沒有更好的方法
感覺我的方法不是很正統的
你要做的是,把 Token 塞到 Call API 的過程用一個 Plugins js 來設定
而不是把塞 Token 的流程綁在 UI 元件裡面。
https://axios-http.com/docs/interceptors
nuxt.config.js
export default {
...,
plugins: [
'~/plugins/axios'
],
...
}
plugins/axios.js
import axios from 'axios'
export default function (ctx, inject) {
axios.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config;
},
error => {
Promise.reject(error)
});
inject('axios', axios)
}
https://axios.nuxtjs.org/extend
nuxt.config.js
export default {
modules: ['@nuxtjs/axios'],
...,
plugins: [
'~/plugins/axios'
],
...
}
plugins/axios.js
export default function ({ $axios, store }) {
$axios.onRequest(() => {
const token = localStorage.getItem('token')
if (token) {
config.headers.common['Authorization'] = `Bearer ${token}`
}
})
}
export default {
async asyncData({ $axios }) {
const test = await $axios.$get('http://test.com')
return { test }
},
mounted() {
this.test = await this.$axios.$get('http://test.com')
}
}
不確定是否正確理解你的問題,主要就是想在 SSR 可以拿到 localstorage,我之前查印象是不行。我是存 Cookie。
cookie-universal-nuxt
我是用這套件就可以在 SSR 拿到 Cookie。
https://www.npmjs.com/package/cookie-universal-nuxt
用這套件很簡單的可以直接 this.$cookies.set('key', 'value')
操作。
用 asyncData 拿 cookie 範例
async asyncData({ app }) {
app.$cookies.get('token')
}
如果你是用 Nuxt3 就更簡單
只要用原生的 useCookie
https://nuxt.com/docs/api/composables/use-cookie
然後寫在 nav.vue 是滿怪的,JWT token Nuxt2 通常用 vuex 來寫才對,我是直接在 vuex index 直接 asyncData,存 vuex global 共用。
Nuxt3 也更方便,直接用 useState 就可以共用資料。
如果上述都沒辦法解決你問題,
暴力解你還可以在 Client 端 mounted -> nextTick() 拿到 localstorage 後打 api。 watch/computed api 拿到資料後同步更新組件資料,在這之間做個障眼法先 opacity 0,watch/computed 更新資料後 opacity 1,來避免畫面閃爍問題。
不知道我有沒有理解錯,我做我的Party Room網頁 時,也有一樣的問題。就是我CALL的API要JWT認證。而JWT TOKEN 在localstorage中。每一次Load網頁時,因為JWT還是在客戶機上,所以CALL API時未有JWT TOKEN就會出錯。
我的解決方法是:
onMounted(async() => {
setTimeout(async() => {
const { data: result, error: error } = await useFetch(
'APILINK',
{
"method": "post",
"headers": {
"Authorization": "token"
}
}
);
}, 100);
});
使用onMounted + settimeOut 0.1秒才CALL API,這樣它就夠時間去讀JWT TOKEN,就不會出錯了~
雖然我不知道是不是正確的做法~