[ Nuxt.js 2.x 系列文章 ] 搭配 Axios 與自訂 Error Page


版本:nuxt 2.15.8

Axios 是一套相當便利的 Promise Base Ajax 套件,而 Nuxt 又有 Axios 整合套件 @nuxtjs/axios

此篇範例會使用到 Async、Await,如果對於 Promise 尚不熟悉,可以參考 Promise 介紹文章

那們我們就來替專案加上 axios 吧!首先執行:npm install @nuxtjs/axios

接著在 nuxt.config.js 進行配置(參數選項):

exportdefault {
  modules: [ '@nuxtjs/axios' ],
    axios: {
        baseUrl: process.env.SERVER_URL,
        browserBaseURL: process.env.BASE_URL,
        credentials: true
    }
}

如果需要區分 client 跟 server 端 base url,可以另外設定 browserBaseURL(於client 端會覆寫 baseUrl),

套件將 axios 方法直接 注入(inject) 至 Vue 實例,擷取套件原始碼片段

// Inject axios to the context as $axios
ctx.$axios = axios
inject('axios', axios)

因此在 Vue 生命週期或屬性使用 this.$axios 即可呼叫 axios 方法,那麽在 Nuxt 生命週期呢?

Nuxt 生命週期(asyncData, fetch, plugins, middleware)會自動帶入 context 參數,context 包含以下參數 / 物件:

const {
        $axios
    app,
    store,
    route,
    params,
    query,
    env,
    isDev,
    isHMR,
    redirect,
    error,
    $config
  } = context

使用方式如下(範例使用 asyncData)

export default {
    async asyncData(context) {
        const { seo } = await context.$axios.$get('/api/seo');
        return {
            seo
        };
    }
}

我們也可以物件解構方式使用 $axios

export default {
    async asyncData({ $axios }) {
        const { seo } = await $axios.$get('/api/seo');
        return {
            seo
        };
    }
}

axios 提供以下方法進行事件捕捉:

  • onRequest(config)
  • onResponse(response)
  • onError(err)
  • onRequestError(err)
  • onResponseError(err)

如果我們想要全域註冊攔截器(Interceptors) 進行 api 請求或是錯誤捕捉,也很簡單,

首先在 plugins 新增檔案,這裡命名為 axios.js,接著在裡面監聽想捕捉的事件方法

export default ({ $axios, redirect, store }) => {
    $axios.onRequest(config => {
    console.log('on request', config.url);
  });
    $axios.onError(error => {
        const code = parseInt(error.response && error.response.status);
        if (code === 401) {
            redirect('/login');
        }
    });
};

接著在 nuxt.config.js plugins 進行擴充

export default {
    plugins: [
        { src: '@/plugins/axios' }
    ]
}

axios 在發生錯誤時,預設會導到 error page,如果我們想避免畫面跳轉,可以加入 resolve promise,這樣在發生錯誤時,都不會跳轉到 error page

export default ({ $axios, redirect, store }) => {
    $axios.onError(error => {
        const code = parseInt(error.response && error.response.status);
        if (code === 401) {
            redirect('/login');
        }
        return Promise.resolve(false); // 避免畫面轉導錯誤頁
    });
};

💡 如果全域設定 resolve promise,在 axios 發生錯誤時,都不會進到 catch error 歐!

自訂 Error Page

Nuxt 專案有預設的 error page,可以在 .nuxt 資料夾看到 components/nuxt-error.vue

錯誤頁面也可以自訂,檔案放置位置比較特別,在 layouts 資料夾內新增一支檔案 error.vue

<template>
    <div class="nuxt-error-wrap">
        <div class="text-center py-4">
            <h2>{{ error.statusCode }}</h2>
            <h3>{{ error.message }}</h3>
        </div>
        <nuxt-link to="/" class="btn btn-primary p-4">回首頁</nuxt-link>
    </div>
</template>

<script>
export default {
    name: 'ErrorPage',
    layout: 'error-layout',
    props: {
        error: {
            type: Object,
            default: () => {}
        }
    }
};
</script>

💡 雖然 error.vue 檔置於 layouts 資料夾,但視為 pages 頁面,因此如果沒有配置 layout,預設會讀取 layouts/default.vue 樣板

這樣就完成了,在 Nuxt 發生錯誤時,都會進到我們自訂錯誤頁面,

如果要手動進到錯誤頁,呼叫 context 內的 error 方法即可,在 Nuxt 生命週期:

export default {
  async asyncData({ $axios, error }) {
    try {
            const { seo } = await $axios.$get('/api/seo');
            return {
                seo
            };
        } catch(err) {
            const { statusCode, message } = err;
            error({ statusCode, message });
        } 
  }
}

在 Vue 生命週期或屬性,使用 this.$nuxt.error() 就可以囉!

export default {
  methods: {
        async getSeo() {
        try {
                const { seo } = await this.$axios.$get('/api/seo');
                this.seo = seo;
            } catch(err) {
                const { statusCode, message } = err;
                this.$nuxt.error({ statusCode, message });
            } 
      }
    }
}

參考文章:

https://ithelp.ithome.com.tw/articles/10208852

https://mavrickmaster.medium.com/custom-error-pages-with-nuxt-js-3c70e6c51aff

#Nuxt #nuxt.js #Vue #Vue.js #ssr #Axios #nuxt-axios







你可能感興趣的文章

[第三週] 用 Jest 寫單元測試

[第三週] 用 Jest 寫單元測試

Virtual DOM 實作與原理解析

Virtual DOM 實作與原理解析

JS Advanced --this

JS Advanced --this






留言討論