iT邦幫忙

0

Nuxt localStorage一問

各位大大好
小弟目前正在用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來執行
不曉得有沒有更好的方法
感覺我的方法不是很正統的

問問題請把程式碼丟出來
不然可能需要找通靈大師
然後請用promise或callback來處理這些需要等待的內容
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
黃彥儒
iT邦高手 1 級 ‧ 2021-11-24 18:34:55
2
通靈亡
iT邦高手 1 級 ‧ 2021-11-24 23:32:41

你要做的是,把 Token 塞到 Call API 的過程用一個 Plugins js 來設定
而不是把塞 Token 的流程綁在 UI 元件裡面。

使用原生 axios 的 request interceptors 設定

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

使用 nuxt/axios 的 onRequest interceptors 設定

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}`
     }
 })
}

呼叫 $axios

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')
  }
}
0
Eason Chiu
iT邦新手 4 級 ‧ 2022-12-08 08:17:51

不確定是否正確理解你的問題,主要就是想在 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,來避免畫面閃爍問題。

0
commonroomhk
iT邦新手 5 級 ‧ 2023-11-11 14:23:46

不知道我有沒有理解錯,我做我的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,就不會出錯了~

雖然我不知道是不是正確的做法~

我要發表回答

立即登入回答