Nuxt.js 是一个基于 Vue.js 的服务端渲染应用框架,它可以帮我们轻松的实现同构应用。
通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI渲染
我们的目标是创建一个灵活的应用框架,你可以基于它初始化新项目的基础结构代码,或者在已有 Node.js 项目中使用 Nuxt.js。
Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
除此之外,我们还提供了一种命令叫: nuxt generate ,为基于 Vue.js 的应用提供生成对应的静态站 点的功能。
我们相信这个命令所提供的功能,是向开发集成各种微服务(Microservices)的 Web 应用迈开的新一步。
作为框架,Nuxt.js 为 客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据 加载、中间件支持、布局支持等非常实用的功能。

特性

  • 基于 Vue.js
    • Vue、Vue Router、Vuex、Vue SSR
  • 自动代码分层
  • 服务端渲染
  • 强大的路由功能,支持异步数据
  • 静态文件服务
  • ES2015+ 语法支持
  • 打包和压缩 JS 和 CSS
  • HTML 头部标签管理
  • 本地开发支持热加载
  • 集成 ESLint 支持各种样式预处理器: SASS、LESS、 Stylus 等等
  • 支持 HTTP/2 推送

Nuxt.js 集成了以下组件/框架,用于开发完整而强大的 Web 应用: Vue.js、Vue Router、Vuex、Vue Server Renderer。
压缩并 gzip 后,总代码大小为:57kb (如果使用了 Vuex 特性的话为 60kb)。
另外,Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 来处理代码的自动化构建工作(如打包、 代码分层、压缩等等)。

创建项目

Nuxt 提供了两种方式用来创建项目: 使用 create-nuxt-app 脚手架工具;手动创建。

手动创建

初始化项目:

  1. # 创建示例项目
  2. mkdir nuxt-app-demo
  3. # 进入示例项目目录中
  4. cd nuxt-app-demo
  5. # 初始化 package.json 文件
  6. npm init -y
  7. # 安装 nuxt
  8. npm innstall nuxt

新增运行脚本:

  1. "scripts": {
  2. "dev": "nuxt"
  3. }

创建 pages 目录,在 pages 目录下创建 index.vue,这是项目的入口文件。

路由

Nuxt.js 会根据 pages 目录中的 vue 文件生成路由配置。
假设 pages 目录的结构如下:

  1. pages/
  2. --| user/
  3. -----| index.vue
  4. -----| one.vue
  5. --| index.vue

那么生成的路由配置如下:

  1. router: {
  2. routes: [
  3. {
  4. name: 'index',
  5. path: '/',
  6. component: 'pages/index.vue'
  7. },
  8. {
  9. name: 'user',
  10. path: '/user',
  11. component: 'pages/user/index.vue'
  12. },
  13. {
  14. name: 'user-one',
  15. path: '/user/one',
  16. component: 'pages/user/one.vue'
  17. }
  18. ]
  19. }

image.png
访问 /user默认跳转到 index.vue,访问 abc.vue 的路径是 /user/abc

路由导航

  • a 标签
  • <nuxt-link />组件
  • 编程式导航
  1. <template>
  2. <div>
  3. <h1>About Page</h1>
  4. <h2>a 链接</h2>
  5. <a href="/">首页</a>
  6. <h2>nuxt-link</h2>
  7. <nuxt-link to="/">首页</router-link>
  8. <h2>编程式导航</h2>
  9. <button @click="btnClick">首页</button>
  10. </div>
  11. </template>
  12. <script>
  13. export default {
  14. name: 'aboutPage',
  15. methods: {
  16. btnClick () {
  17. this.$router.push('/')
  18. }
  19. },
  20. }
  21. </script>

动态路由

在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。 以下目录结构:

  1. pages/
  2. --| _slug/
  3. -----| comments.vue
  4. -----| index.vue
  5. --| users/
  6. -----| _id.vue
  7. --| index.vue

生成的路由配置:

  1. router: {
  2. routes: [
  3. {
  4. name: 'index',
  5. path: '/',
  6. component: 'pages/index.vue'
  7. },
  8. {
  9. name: 'users-id',
  10. path: '/users/:id?',
  11. component: 'pages/users/_id.vue'
  12. },
  13. {
  14. name: 'slug',
  15. path: '/:slug',
  16. component: 'pages/_slug/index.vue'
  17. },
  18. {
  19. name: 'slug-comments',
  20. path: '/:slug/comments',
  21. component: 'pages/_slug/comments.vue'
  22. }
  23. ]

名称为 users-id 的路由路径带有 :id? 参数,表示该路由是可选的。如果你想将它设置为必选的路由,需要在 users/_id 目录内创建一个 index.vue 文件。

image.png
访问/user/5,访问 _id.vue,传入 _id.vue 的参数 id 的值就是 5。

嵌套路由

你可以通过 vue-router 的子路由创建 Nuxt.js 应用的嵌套路由。
创建内嵌子路由,你需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
别忘了在父组件( .vue 文件) 内增加<nuxt-child />用于显示子视图内容。
屏幕截图 2022-02-06 220927.png

  1. <template>
  2. <div>
  3. <h1>User 父路由</h1>
  4. <!-- 留给子路由的位置,默认加载 index.vue -->
  5. <nuxt-child />
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. }
  11. </script>

自定义路由配置

在配置文件nuxt.config.js中配置。

  1. module.exports = {
  2. router: {
  3. base: '/app', // 基本路径,默认是 /
  4. extendRoutes (routes, resolve) {
  5. routes.push({ // 自己添加路由规则
  6. path: '/hello',
  7. name: 'hello',
  8. component: resolve(__dirname, 'pages/about.vue')
  9. })
  10. }
  11. }
  12. }

页面模板

在根目录下创建 app.html,Nuxt.js 会把它作为渲染模板。

  1. <!DOCTYPE html>
  2. <html {{ HTML_ATTRS }}>
  3. <head {{ HEAD_ATTRS }}>
  4. {{ HEAD }}
  5. </head>
  6. <body {{ BODY_ATTRS }}>
  7. <h1>app.html</h1>
  8. <!-- index.vue 渲染位置 -->
  9. {{ APP }}
  10. </body>
  11. </html>

nuxt-views-schema.svg

页面布局

Nuxt.js 把layouts目录作为存放布局组件的位置。
image.png

布局组件中需要预留一个<nuxt />标签,这个就是使用该布局组件的页面组件的渲染位置。

  1. <template>
  2. <div>
  3. <h1>layouts/foo 组件</h1>
  4. <nuxt/>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'LayoutFoo'
  10. }
  11. </script>

页面组件如果不指定布局组件或者指定一个不存在的布局组件,默认会使用 default.vue 的布局。

  1. <template>
  2. <div>
  3. <h1>Hello NuxtJS!</h1>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'index',
  9. layout: 'foo' // 如果不指定,默认使用 default.vue 的布局
  10. }
  11. </script>

异步数据

Nuxt.js 扩展了 Vue.js,增加了一个叫asyncData的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。
asyncData 的调用时机是服务端渲染期间和客户端路由更新之前。
asyncData 返回的数据会和 vue 的 data 返回的数据合并,一并给组件。
需要注意:

  • asyncData 只能在页面组件中使用,子组件中无法使用。
  • asyncData 没有 this 的概念,因为它是在组件初始化之前被调用的。

上下文对象

asyncData 接收一个上下文对象,这个对象里包含了当前的路由规则,也包含传入参数。

  1. <template>
  2. <div>
  3. <h1>{{ article.title }}</h1>
  4. <div>{{ article.body }}</div>
  5. </div>
  6. </template>
  7. <script>
  8. import axios from 'axios'
  9. export default {
  10. name: 'Article',
  11. async asyncData(context) {
  12. const { data } = await axios({
  13. method: 'GET',
  14. url: 'http://localhost:3000/data.json'
  15. })
  16. const id = Number.parseInt(context.params.id)
  17. return {
  18. article: data.posts.find(item => item.id === id)
  19. }
  20. },
  21. }
  22. </script>