https://zh.nuxtjs.org/docs/2.x/get-started/installation
https://www.nuxtjs.cn/api/components-client-only

  1. yarn create nuxt-app <project-name>
  2. npm init nuxt-app <project-name>
  3. npx create-nuxt-app <project-name>

Routing 路由

文件路由系统
大多数网站将有多个页面(即主页、关于页面、联系页面等)。为了显示这些页面,我们需要一个路由器。这就是vue-router切入点。在使用 Vue 应用程序时,您必须设置一个配置文件(即router.js)并手动将所有路由添加到其中。Nuxt.js 会vue-router根据您提供的 pages 目录中的 Vue 文件自动为您生成 配置 。这意味着您永远不必再次编写路由器配置!Nuxt.js 还为您提供所有路由的自动代码拆分。
换句话说,要在应用程序中进行路由,您所要做的就是.vue在pages文件夹中创建文件。

  1. window.location.href = '/search' // 可以用这个跳转
  2. <nuxt-link to="/index"></nuxt-link> // 使用nuxt-link 做跳转
  3. this.$router.push('/test')
  4. this.$router.replace('/test')

本地访问路由参数

  1. 您可以通过引用访问本地页面或组件中的当前路由参数 this.$route.params.{parameterName}。举例来说,如果你有一个动态的用户页面(users/_id.vue),并希望访问 id 加载的用户或进程的信息参数,你可以访问这样的变量: this.$route.params.id

嵌套路由

  1. Nuxt.js 允许您使用 vue-router 的子路由创建嵌套路由。要定义嵌套路由的父组件,您需要创建一个与包含子视图的目录同名的 Vue 文件。<br />要忘记在父组件( 文件)中包含 [NuxtChild 组件](https://zh.nuxtjs.org/docs/2.x/features/nuxt-components#the-nuxtchild-component).vue
  1. pages/
  2. --| users/
  3. -----| _id.vue
  4. -----| index.vue
  5. --| users.vue
  6. // 会自动生成
  7. router: {
  8. routes: [
  9. {
  10. path: '/users',
  11. component: 'pages/users.vue',
  12. children: [
  13. {
  14. path: '',
  15. component: 'pages/users/index.vue',
  16. name: 'users'
  17. },
  18. {
  19. path: ':id',
  20. component: 'pages/users/_id.vue',
  21. name: 'users-id'
  22. }
  23. ]
  24. }
  25. ]
  26. }

keep-alive 嵌套路由

Both, the component and the component, accept keep-alive and keep-alive-props.

  1. <!-- layouts/default.vue -->
  2. <template>
  3. <div>
  4. <Nuxt keep-alive :keep-alive-props="{ exclude: ['modal'] }" />
  5. </div>
  6. </template>
  7. <!-- 将被转换成这样的东西 -->
  8. <div>
  9. <KeepAlive :exclude="['modal']">
  10. <RouterView />
  11. </KeepAlive>
  12. </div>
<!-- pages/parent.vue -->
<template>
  <div>
    <NuxtChild keep-alive :keep-alive-props="{ exclude: ['modal'] }" />
  </div>
</template>

<!-- 将被转换成这样的东西 -->
<div>
  <KeepAlive :exclude="['modal']">
    <RouterView />
  </KeepAlive>
</div>
<template>
  <div>
    <NuxtChild :key="$route.params.id" />
  </div>
</template>

404 路由

pages/
--| people/
-----| _id.vue
-----| index.vue
--| _.vue
--| index.vue

/ -> index.vue
/people -> people/index.vue
/people/123 -> people/_id.vue
/about -> _.vue
/about/careers -> _.vue
/about/careers/chicago -> _.vue

scrollBehavior

允许您为路由之间的滚动位置定义自定义行为。每次呈现页面时都会调用此方法。vue-router scrollBehavior 文档可用版本:v2.9.0:
在 Nuxt.js 中,您可以使用文件覆盖路由器 scrollBehavior。这个文件应该放在一个名为 app 的文件夹中。
~/app/router.scrollBehavior.js.
Nuxt.js 默认router.scrollBehavior.js文件。
scrollBehavior 属性

目录结构

pages 页面目录
components 组建目录
assets 资产目录 存放样式,图像,字体
static 静态文件目录
nuxt.config.js 配置文件

Components 自动导入,与使用

component

命令和部署

target: server 默认的

  • nuxt dev- 启动开发服务器。
  • nuxt build- 使用 webpack 构建和优化您的应用程序以进行生产。
  • nuxt start - 启动生产服务器(运行后nuxt build)。将它用于 Node.js 托管,如 Heroku、Digital Ocean 等。

    target: static

    配置 nuxt.config.js

    export default {
    target: 'static'
    }
    
  • nuxt dev- 启动开发服务器。

  • nuxt generate- 构建应用程序(如果需要),将每个路由生成为 HTML 文件并静态导出到dist/目录(用于静态托管)。
  • nuxt start -dist/像静态托管一样提供目录(Netlify、Vercel、Surge 等),非常适合在部署前进行测试。

    npm run generate

    export default {
    generate: {
      dir: 'myapp3', // 默认情况下生成dist文件夹,修改以后生成myapp3文件夹
      subFolders: true, // 默认情况下 /demo/fetch.vue 会生成/demo/fetch/index.html, 设置成ture以后就生成 /demo/fetch.html
      fallback: '404.html', // 默认是200.html 都是nuxt自动生成的
      exclude: [/demo/], // 不编译那些页面
    }
    }
    

自定义布局

您可以通过将.vue文件添加到 layouts 目录来创建自定义布局。
使用default.vue布局

<template>
  <div>
    <div>My blog navigation bar here</div>
    <Nuxt />
  </div>
</template>

您可以通过添加layouts/error.vue 文件来自定义错误页面 :

<template>
  <div>
    <h1 v-if="error.statusCode === 404">Page not found</h1>
    <h1 v-else>An error occurred</h1>
    <NuxtLink to="/">Home page</NuxtLink>
  </div>
</template>

<script>
  export default {
    props: ['error'],
    layout: 'error' // you can set a custom layout for the error page
  }
</script>

App.html

您可以通过app.html 在项目的源目录(默认为根目录)中创建文件来自定义 Nuxt.js 使用的 HTML 应用程序模板以包含脚本或条件 CSS 类 。
app.html

<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
  <head {{ HEAD_ATTRS }}>
    {{ HEAD }}
  </head>
  <body {{ BODY_ATTRS }}>
    {{ APP }}
  </body>
</html>

兼容

<!DOCTYPE html>
<!--[if IE 9]><html class="lt-ie9 ie9" {{ HTML_ATTRS }}><![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--><html {{ HTML_ATTRS }}><!--<![endif]-->
  <head {{ HEAD_ATTRS }}>
    {{ HEAD }}
  </head>
  <body {{ BODY_ATTRS }}>
    {{ APP }}
  </body>
</html>

layouts

yarn create nuxt-app 默认创建的project没有layouts, 但是可以手动加入此文件夹, 创建default.vue, error.vue nuxt会自动读

<!-- /layouts/default.vue -->
<template>
  <div>
    <h1>layouts</h1>
    <nuxt v-if="isKeepAlive" keep-alive />
    <nuxt v-else />
  </div>
</template>

<script>
export default {
  data() {
    return {
      isKeepAlive: true
    }
  }
}
</script>

<!-- /layouts/error.vue -->
<template>
  <div class="error-page">
    error-page
  </div>
</template>

<script>
export default {
}
</script>
<style lang="less" scoped>
</style>

Nuxt 生命周期

nuxt 生命周期详解
image.png

fetch 钩子

此钩子在服务器端和客户端都会被执行
fetch 是在创建组件实例后在服务器端渲染期间以及在客户端导航时调用的钩子
fetchOnServer:false, // 可以通过设置这个让服务器端不执行

before-create
created
beforeMount
fetch // fetch 钩子 $fetchState.pending = true
mounted
fetch // fetch 钩子 $fetchState.pending = true
before-update $fetchState.pending = false
updated

<template>
  <p v-if="$fetchState.pending">Fetching mountains...</p>
  <p v-else-if="$fetchState.error">An error occurred :(</p>
  <div v-else>
    <h1>Nuxt Mountains</h1>
    <ul>
      <li v-for="mountain of mountains" :key="mountain.title">{{ mountain.title }}</li>
    </ul>
    <button @click="$fetch">Refresh</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      mountains: [],
    };
  },
  async fetch() {
    console.log('$fetchState:start:', this.$fetchState) // $fetchState.pending = true
    this.mountains = await fetch("https://api.nuxtjs.dev/mountains").then(
      (res) => {
        console.log(res);
        console.log('$fetchState:axios-end:', this.$fetchState) // $fetchState.pending = true
        return res.json();
      }
    );
    console.log('$fetchState:end:', this.$fetchState) // $fetchState.pending = true

    // 当fetch钩子执行完毕 $fetchState.pending 会自动变成false
  },
};
</script>

asyncData

asyncData是另一个用于通用数据获取的钩子。与fetch需要您在组件实例上设置属性(或调度 Vuex 操作)以保存异步状态的 不同,asyncData只需将其返回值合并到组件的本地状态即可。<br />这个钩子只能用于页面级组件。与 不同fetch,asyncData无法访问组件实例 ( this)。相反,它接收 [上下文](https://zh.nuxtjs.org/docs/2.x/concepts/context-helpers) 作为其参数。您可以使用它来获取一些数据,Nuxt.js 会自动将返回的对象与组件数据进行浅合并。<br />    asyncData会在路由转换期间完成,客户端不可见,在导航到下一页或显示[错误页面](https://zh.nuxtjs.org/docs/2.x/directory-structure/layouts#error-page)之前等待钩子完成<br />    注意:前台看不到此请求<br />结合keep-alive使用的顺序,他执行在before-create,create之前<br />asyncData {} undefined<br />asyncData res<br />$fetchState:start: true<br />$fetchState:end: true<br />before-update<br />updated<br />before-update<br />updated
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.description }}</p>
  </div>
</template>

<script>
  export default {
    async asyncData({ params, $http }) {
      const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
      return { post }
    }
  }
</script>

所以你不能直接在组件内获取异步数据服务器端。为了解决这个限制,您有三个基本选项:

  1. 使用Nuxt 2.12 及更高版本中提供的新fetch钩子
  2. 在mounted挂钩中调用 API并在加载时设置数据属性。缺点:不适用于服务器端渲染。
  3. asyncData在页面组件的方法中进行API调用,将数据作为props传递给子组件。服务器渲染将正常工作。缺点:asyncData页面的可读性可能较差,因为它正在加载其他组件的数据。

fetch与asyncData的区别

两者不同
执行时机不同
fetch发生在created之后,fetch可以通过$fetchState获取fetch的状态。
asyncData发生在路由阶段(route),asyncData没有获取状态的方法。
发生错误不一样
asyncData发生在路由阶段,如果执行过程中发生了错误,那么就会进入错误页面,整个页面打不开。
fetch发生在页面渲染之前,此时页面已经打开了,如果发生了错误,那么$fetchData.error为true,页面还是存在的。
范围不同
fetch在页面(page目录下)和组件(components目录下)都可以执行;
asyncData只是在页面(page目录下)才执行。
参数不同
fetch方法不能传参数,需要通过this.$nuxt.context获取context。
asyncData方法可以接受context参数。
意义不同
fetch可以操作页面上data中的对象。
asyncData返回的结果将和页面上data进行合并,再渲染页面。