在 asyncData 中访问上下文

我们可以从 Nuxt 上下文中访问大量有用的东西来获取数据。它们作为以下键存储在 context 对象中:

  • app

  • route

  • store

  • params

  • query

  • req

  • res

  • redirect

  • error

  • env

  • isDev

  • isHMR

  • beforeNuxtRender(fn)

  • from

  • nuxtState

它们是额外提供的,并且仅在 Nuxt 中可用,因此我们在 Vue 中找不到它们。我们可以使用 context.<key>{ <key> } 来访问它们。因此,让我们在接下来的章节中探讨其中的一些键,看看如何利用它们。

有关 Nuxt 上下文的更多信息,请访问 https://nuxtjs.org/api/context

访问 req/res 对象

asyncData 方法在服务器端执行时,我们可以访问 reqres 对象。它们包含来自用户的 HTTP 请求的有用信息。但是,在访问它们之前,我们应该始终使用 if 条件进行检查:

// pages/index.vue
<p>{{ host }}</p>
<script>
export default {
  asyncData ({ req, res }) {
    if (process.server) {
      return { host: req.headers.host }
    }
    return { host: '' }
  }
}
</script>

在上面的代码中,我们使用 if 条件来确保在获取请求头信息之前,asyncData 方法是在服务器端调用的。这两个对象在客户端是不可用的,因此在客户端访问它们时,你会得到 undefined。因此,当首次在浏览器中加载页面时,我们从上面的代码中得到的结果将是 localhost:3000,但是当你通过 <nuxt-link> 组件生成的路由重新访问此页面时,除非你刷新该页面,否则你将不会再次看到该信息。

访问动态路由数据

当我们的应用程序中存在动态路由时,我们可以通过 params 键访问动态路由数据。例如,如果我们在 /pages/ 目录下有一个 _id.vue 文件,那么我们可以通过 context.params.id 访问路由参数的值,如下所示:

// pages/users/_id.vue
<p>{{ id }}</p>
<script>
export default {
  asyncData ({ params }) {
    return { id: params.id }
  }
}
</script>

在上面的代码中,当你在浏览器中访问 users/1 时,你将得到 1 作为 id 的值。

监听查询变化

默认情况下,asyncData 方法不会在查询字符串发生变化时执行。例如,如果你在你的路由中使用类似 /users?id=<id> 这样的查询,并通过 <nuxt-link> 组件进行导航,那么当你通过 <nuxt-link> 组件的路由从一个查询切换到另一个查询时,asyncData 不会被调用。这是因为为了提高性能,Nuxt 默认禁用了对查询变化的监听。如果你想覆盖这个默认行为,你可以使用 watchQuery 属性来监听特定的参数:

// pages/users/index.vue
<p>{{ id }}</p>
<ul>
  <li><nuxt-link :to="'users?id=1'">1</nuxt-link>
  <nuxt-link :to="'users?id=2'">2</nuxt-link></li>
</ul>
<script>
export default {
  asyncData ({ query }) {
    return { id: query.id }
  },
  watchQuery: ['id']
}
</script>

在上面的代码中,我们监听了 id 参数,因此当你导航到 /users?id=1 时你会得到 1,而导航到 /users?id=2 时你会得到 2。如果你想为所有查询字符串设置监听器,只需将 watchQuery 设置为 true 即可。

处理错误

我们可以使用上下文对象中的 error 方法来调用 Nuxt 的默认错误页面并显示错误。你可以通过默认的 params.statusCodeparams.message 属性传递错误代码和消息:

// pages/users/error.vue
export default {
  asyncData ({ error }) {
    return error({
      statusCode: 404,
      message: 'User not found'
    })
  }
}

如果你想更改传递给 error 方法的默认属性,你可以创建一个自定义错误页面,这在第四章 “添加视图、路由和过渡” 中已经学过。让我们通过以下步骤创建这些自定义错误属性和布局:

  1. 创建一个你想将自定义属性传递给的页面:

    // pages/users/error-custom.vue
    export default {
      asyncData ({ error }) {
        return error({
          status: 404,
          text: 'User not found'
        })
      }
    }
  2. /layouts/ 目录下创建一个自定义错误页面:

    // layouts/error.vue
    <template>
      <div>
        <h1>Custom Error Page</h1>
        <h2>{{ error.status }} Error</h2>
        <p>{{ error.text }}</p>
        <nuxt-link to="/">Home page</nuxt-link>
      </div>
    </template>
    <script>
    export default {
      props: ['error'],
      layout: 'layout-error'
    }
    </script>
  3. 为这个错误页面创建一个自定义布局页面:

    // layouts/layout-error.vue
    <template>
      <nuxt />
    </template>

访问 /users/error-custom 时,你应该会看到自定义属性和布局。

你可以在我们的 GitHub 仓库的 /chapter-8/nuxt-universal/koa-nuxt/accessing-context/ 目录下找到所有这些示例。

接下来,我们将在下一节中了解如何在 asyncData 方法中使用 HTTP 客户端 Axios 来请求 API 数据。