Vue / Nuxt.js:如何在嵌套路由(nuxt-child)上处理404

时间:2018-06-22 06:47:04

标签: vue.js nested http-status-code-404 axios nuxt.js

我正在使用来自nuxt.js的嵌套路由: https://nuxtjs.org/guide/routing#nested-routes 带有子组件: https://nuxtjs.org/api/components-nuxt-child/

为了便于理解: 我有一个事件页面和一个嵌套的postView组件。 左侧,您会看到一个日历视图,即使路线发生变化,该视图也将保留。 右边有替换后的细节(nuxt子组件):

enter image description here

使用Nuxt,此文件夹/文件设置将正确设置我的路由器。

到目前为止,该方法仍然有效,但是如果有人在URL中输入了不存在的postSlug,我现在想处理这种情况。 到目前为止,它只是不会显示,但我想有一个正确的404代码。 我必须手动设置吗? (我目前正在从calendarview进行axios调用,以查看post.json是否存在。如果存在,则将其加载到vuex存储中)

  …
  // if it is not in store get it via axios
  else {

    const ax = axios.create({
      baseURL: `${window.location.origin}/events`
    })
    ax.get(`event.${this.$route.params.postSlug}.json`)
    .then((response) => {
      const newActivePost = response.data && response.data.items ? response.data.items.find(p => p.slug === this.$route.params.postSlug) : false
      if (newActivePost) {
        this.activePost = newActivePost
        this.$store.dispatch('data/saveCompletePosts', this.activePost)
      }
    })
    .catch((error) => {
      console.log(error.response.data)
      console.log(error.response.status)
      console.log(error.response.headers)
    })
  }

但是,我永远不会出错。即使json文件不存在。我总是收到200状态代码。

我不确定为什么会这样,但是响应可能只包含页面,而没有帖子本身。如果我用缺少的帖子调用该网址,则实际上是相同的。如果我看一下响应字符串:

<body data-n-head="">
  <div data-server-rendered="true" id="__nuxt">
    <div class="nuxt-progress" style="width:0%;height:2px;background-color:#000000;opacity:0;"></div>
    <div id="__layout">
      <div class="Layout">
        <!---->
        <div class="SkipNavigationLink"><a href="#main" class="SkipNavigationLink__link">Springe direkt zum Hauptinhalt</a></div>
        <div class="no-ssr-placeholder"></div>
        <main id="main" class="Layout__content">
          <!---->
        </main>
        <div class="Footer">
          <div class="Footer__logo-wrapper">
            <div class="Logo"><a href="/" aria-label="Home" class="Logo__link is-active"><img src="/_nuxt/img/logo-dark.0b2ed1f.svg" alt="Logo Image" class="Logo__image"></a></div>
          </div>

您可以看到有布局和页脚,但没有内容。 我的猜测是,如果我可以在嵌套的route / child组件中返回正确的404状态代码,那么我的axios响应中也会得到404。

一个(也许是个怪异的主意)将是手动设置状态代码:

    ax.get(`event.${this.$route.params.postSlug}.json`)
    .then((response) => {

      const newActivePost = response.data && response.data.items ? response.data.items.find(p => p.slug === this.$route.params.postSlug) : false
      if (newActivePost) {
        this.activePost = newActivePost
        this.$store.dispatch('data/saveCompletePosts', this.activePost)
      } else {
        // SET STATUS CODE MANUALLY?
        response.request.status = 404
      }
    })

然后以不同的方式处理事情。 但是我不知道这是一个好主意...

非常感谢有关nuxt路由/ 404处理的一些帮助。

欢呼

--------编辑 我刚发现这个 https://nuxtjs.org/api/pages-validate 我认为这实际上将称为404,但我不知道如何验证,因为postSlug中没有模式。 我真的必须检查帖子的所有json文件...

------编辑2:  我什至不能这样做: TypeError: Cannot assign to read only property 'status' of object '#<XMLHttpRequest>' ‍♂️

2 个答案:

答案 0 :(得分:0)

我认为您正在寻找context的错误函数

  async asynData({ params, store, error }) {
    try {
      await axioscall here
    } catch (e) {
      error({ statusCode: 404, message: 'Page not found' })
    }
  },

答案 1 :(得分:0)

不确定是否相关,我重定向到在顶级页面目录 (pages/_.vue) 中工作的错误页面,如下所示:

  async asyncData(context) {
    ...
    try {
      const response = await context.$axios(options);

      return {
        isPostLoaded: true,
        loadedPost: response.data.data.postBy
      }
    } catch (error) {
      context.error({ statusCode: 404, message: 'Page not found' });
    }
}

但它在页面的嵌套目录中不起作用(pages/posts/_slug/index.vue) 添加这似乎有帮助,我检查了响应数据是否可用(可能不是最好的方法,但似乎有效)

if (response.data.data.postBy === null) {
  throw new Error();
}

...

async asyncData(context) {
...
    try {
      const response = await context.$axios(options);
    
      if (response.data.data.postBy === null) {
        throw new Error();
      }
    
      return {
        isPostLoaded: true,
        loadedPost: response.data.data.postBy
      }
    } catch (error) {
      context.error({ statusCode: 404, message: 'Page not found' });
    }
}