Skip to content

Nuxt3

[TOC]

概述

什么是Nuxt

Nuxt官方文档:https://nuxt.com.cn/docs/getting-started/installation

在了解 Nuxt 之前,我们先来了解一下创建一个现代应用程序,所需的技术:

  • 支持数据双向绑定和组件化( Nuxt 选择了 Vue.js )。
  • 处理客户端的导航( Nuxt 选择了 vue-router )。
  • 支持开发中热模块替换和生产环境代码打包( Nuxt 支持 webpack 5 和 Vite )。
  • 兼容旧版浏览器,支持最新的 JavaScript 语法转译( Nuxt 使用 esbuild )。
  • 应用程序支持开发环境服务器,也支持服务器端渲染 或 API 接口开发。
  • Nuxt 使用 h3 来实现部署可移植性(h3 是一个极小的高性能的 http 框架)
    • 如:支持在 Serverless、Workers 和 Node.js 环境中运行。
    • image-20240911151818836

Nuxt是一个直观的Web框架

  • 自2016年10月以来,Nuxt 专门负责集成上述所描述的事情 ,并提供前端和后端的功能。
  • Nuxt 框架可以用来快速构建一个 Vue.js 应用程序,如支持 CSR 、SSR、SSG 渲染模式的应用等。

Nuxt发展史

Nuxt.js:

  • 诞生于2016年10月25号,由 Sebastien Chopin 创建,主要是基于 Vue2 、Webpack2 、Node 和 Express。
  • 在 2018年1月9日, Sebastien Chopin 正式宣布,发布 Nuxt.js 1.0 版本。
    • 重要的变化是放弃了对 node < 8 的支持
  • 2018年9月21日, Sebastien Chopin 正式宣布,发布 Nuxt.js 2.0 版本。
    • 开始使用 Webpack 4 及其技术栈, 其它的并没有做出重大更改。
  • 2021年8月12日至今,Nuxt.js 最新的版本为:Nuxt.js 2.15.8

Nuxt3:

  • 经过16个月的工作,Nuxt 3 beta 于2021年10月12日发布,引入了基于 Vue3、Vite 和 Nitro( 服务引擎 ) 。
  • 六个月后,2022年4月20日,Pooya Parsa 宣布 Nuxt3 的第一个候选版本,代号为“Mount Hope”。
  • 2022年11月16号, Pooya Parsa 再次宣布 Nuxt3 发布为第一个正式稳定版本

Nuxt3特点

  • Vue技术栈

    • Nuxt3是基于Vue3 + Vue Router + Vite等技术栈,全程Vue3+Vite开发体验(Fast)。
  • 自动导包

    • Nuxt 会自动导入辅助函数组合APIVue API ,无需手动导入。
    • 基于规范的目录结构,Nuxt 还可以对自己的组件插件使用自动导入。
  • 约定式路由

    • Nuxt路由基于vue-router,在pages目录中创建的每个页面,都会根据目录结构和文件名来自动生成路由
  • 渲染模式

    • Nuxt支持多种渲染模式(SSRCSRSSG 等)

      image-20240911151850083

  • 利于搜索引擎优化

    • 服务器端渲染模式,不但可以提高首屏渲染速度,还利于SEO
  • 服务器引擎

    • 开发环境中,它使用 RollupNode.js

    • 生产环境中,使用 Nitro 将您的应用程序和服务器构建到一个通用.output目录中。

      Nitro服务引擎提供了跨平台部署的支持,包括 Node、Deno、Serverless、Workers 等平台上部署。

Nuxt.js VS Nuxt3

image-20240911151901743

基础

环境搭建

前置环境:

  • Node.js:v18.0.0 或更新版本,推荐使用偶数版本。
  • 文本编辑器:我们推荐使用 Visual Studio Code 以及 Volar(Vue - Official) 扩展
  • 终端:用于运行 Nuxt 命令

新建项目:

1、在命令行中,运行以下命令:

sh
# pnpm
pnpm dlx nuxi init <project-name>

# npm
npx nuxi init <project-name>

2、进入到<project-name>目录,安装依赖。

sh
pnpm install

# 以前需要携带以下参数,用来创建一个扁平的node_modules目录结构
# pnpm install --shamefully-hoist

错误: 执行npx nuxi init 01-hello-nuxt 报如下错误:

image-20241007115137701

image-20240925181216112

分析:主要是网络不通导致。

解决:配置host翻墙

1、ping raw.githubusercontent.com 检查是否通。如果访问不通,代表是网络不通。

2、配置 host,本地解析域名:

  • Mac 电脑 host 配置路径: /etc/hosts
  • Win 电脑 host 配置路径:c:/Windows/System32/drivers/etc/hosts

3、在 host 文件中新增一行 ,编写如下配置:

sh
185.199.108.133 raw.githubusercontent.com

# 或者以下其中一个
185.199.108.133 raw.githubusercontent.com
185.199.109.133 raw.githubusercontent.com
185.199.110.133 raw.githubusercontent.com
185.199.111.133 raw.githubusercontent.com

4、重新 ping 域名,如果通了就可以用了。

5、重新开一个终端创建项目即可。

目录结构

image-20240911152025639

package.json脚本:

image-20240925220356405

注意: postinstall 是一种npm生命周期脚本,在安装依赖包后自动执行。它可以用于执行一些初始化任务,比如构建项目、复制文件或设置环境变量。

json
"scripts": {
  "postinstall": "node setup.js"
}

app.vue

默认情况下,Nuxt 会将此文件视为入口,并为应用程序的每个路由呈现其内容。

作用:

  • 布局:定义页面布局 Layout 或 自定义布局,如:<NuxtLayout>
  • 路由占位:定义路由的占位,如:<NuxtPage>
  • 编写全局样式
  • 全局监听路由

image-20240911152103373

配置

▸nuxt.config

nuxt.config.ts 配置文件位于项目的根目录,可对 Nuxt 进行自定义配置。

Nuxt配置:

  • runtimeConfig{ public, 自定义 }运行时配置,即定义环境变量。支持服务器和客户端的变量。

    • 注意: 配置会被.env配置覆盖。

    • public{ 自定义 },这个部分的配置会被公开到客户端,因此可以在前端服务端代码中都可以安全使用。

      • 自定义:``,自定义的环境变量。
    • ...自定义:``,自定义的私有环境变量。这个部分的配置仅在服务器端可用,不能被客户端访问。

    • js
      // 1. 在runtimeConfig 中定义环境变量
      runtimeConfig: {
        public: {
          apiUrl: process.env.API_URL,
          xxx: 'http://baidu.com'
        },
        yyy: 'yyy',
        zzz: 'zzz'
      },
      js
      // 2. 访问环境变量:useRuntimeConfig()
      const config = useRuntimeConfig()
      
      // 在客户端
      if(process.client) {
      	const apiUrl = config.public.apiUrl
      }
      
      // 在服务器端
      if(process.server) {
      	const apiUrl = config.public.apiUrl
      	const secret = config.yyy
      }
  • appConfig{ 自定义 },应用配置,定义在构建时确定的公共变量,如:theme。

    • 注意: 配置会和app.config.ts配置合并。优先级: app.config.ts > appConfig

    • 注意: 前后端都可以访问配置项。

    • js
      export default defineNuxtConfig({
        appConfig: {
          siteName: 'My Awesome Site',
          apiBase: process.env.API_BASE_URL || 'https://api.example.com'
        }
      })
    • js
      // 访问配置:useAppConfig()
      const appConfig = useAppConfig()
      
      console.log(appConfig.siteName) // 输出: My Awesome Site
      console.log(appConfig.apiBase)   // 输出: https://api.example.com
  • app{baseURL, head},应用相关的配置,如头部信息、全局样式等。

    • baseURLstring,定义应用的基础 URL,通常用于处理相对路径。

    • buildAssetsDirstring,用于自定义构建生成的静态资产的目录。

    • cdnURLstring,用于指定 CDN(内容分发网络)的基本 URL,这样你可以将静态资源托管在 CDN 上,提高加载速度。

    • head{title, meta, link, style, script},给每个页面上设置 head 信息,也支持 useHead 配置和内置组件。

      • titlestring,标题。

      • meta[{charset},{ name, content}],元数据。

        • {charset}:``,字符编码。
        • { name, content}:``,
      • link[{rel, href}],外链样式。

      • style[{children, type}],样式。

      • script[{src, body?}],JS脚本。

        • src:``,script连接地址。
        • body?boolean是否将script添加到body标签中。
    • js
        app: {
          baseURL: '/my-app/',
          buildAssetsDir: 'static/assets/', // 自定义静态资源目录
          cdnURL: 'https://cdn.example.com/', // 替换为你的CDN地址
          head: {
            meta: [
              // <meta name="viewport" content="width=device-width, initial-scale=1">
              { name: 'viewport', content: 'width=device-width, initial-scale=1' }
            ],
          script: [
            // <script src="https://myawesome-lib.js"></script>
            { src: 'https://awesome-lib.js' }
          ],
          link: [
            // <link rel="stylesheet" href="https://myawesome-lib.css">
            { rel: 'stylesheet', href: 'https://awesome-lib.css' }
          ],
          // please note that this is an area that is likely to change
          style: [
            // <style type="text/css">:root { color: red }</style>
            { children: ':root { color: red }', type: 'text/css' }
          ],
          noscript: [
            // <noscript>JavaScript is required</noscript>
            { children: 'JavaScript is required' }
          ]
        }
      }
  • ssrboolean默认:true,指定应用的渲染模式。

    • true:开启SSR渲染。
    • false:关闭SSR渲染,此时属于SPA应用。
  • router{base, middleware, options},配置路由相关的信息,比如在客户端渲染可以配置 hash 路由。

    • basestring,用于设置应用的基础路径。如果你的应用部署在一个子目录下,可以通过这个选项来指定。

    • middlewarestring[],指定全局中间件,可在每个页面的渲染之前执行一些逻辑,如身份验证等。

    • options{hashMode}

      • hashModeboolean,是否使用hash路由(只在SPA应用中有效)。开启hash路由
    • js
      router: {
        base: '/app/',
        middleware: ['auth'],
        options: {
            hashMode: true // hash路由
        }
      },
    • js
      // 开启hash路由
      export default defineNuxtConfig({
        ssr: false,
        router: {
          options: {
            hashMode: true
          }
        }
      })
  • cssstring[],全局 CSS 文件。

    • js
      css: ['@/assets/styles/global.css'],
  • modulesstring[],引入 Nuxt 模块,增强功能。

    • js
      modules: ['@nuxtjs/axios', '@nuxtjs/pwa'],
  • plugins[{src, mode}],定义插件,支持客户端和服务端。

    • src:``,

    • mode:``,

    • js
      plugins: [{ src: '~/plugins/myPlugin.js', mode: 'client' }],
  • routeRules:``,定义路由规则,可更改路由的渲染模式或分配基于路由缓存策略(公测阶段)

    • :``,
  • middlewarestring[],定义全局中间件。

    • js
      router: {
        middleware: ['auth'],
      },
  • alias:``,路径的别名,默认已配好。

    • :``,
  • build{extractCSS, extend(config, { isDev })},Webpack 构建相关配置。

    • extractCSS:``,

    • extend(config, { isDev }):``,

    • js
      build: {
        extractCSS: true,
        extend(config, { isDev }) {
          if (isDev) {
            config.devtool = 'source-map';
          }
        },
      },
  • builder:``,可指定用 vite 还是 webpack 来构建应用,默认是 vite。如切换为 webpack 还需要安装额外的依赖。

    • :``,
  • i18n{locales, defaultLocale},配置国际化支持。

    • locales[{code, name}]

      • code:``,
      • name:``,
    • defaultLocalestring

    • js
      i18n: {
        locales: [
          { code: 'en', name: 'English' },
          { code: 'fr', name: 'Français' },
        ],
        defaultLocale: 'en',
      },
runtimeConfig
  • runtimeConfig{ public, 自定义 }运行时配置,即定义环境变量。支持服务器和客户端的变量。

    • 注意: 配置会被.env配置覆盖。

    • public{ 自定义 },这个部分的配置会被公开到客户端,因此可以在前端服务端代码中都可以安全使用。

      • 自定义:``,自定义的环境变量。
    • ...自定义:``,自定义的私有环境变量。这个部分的配置仅在服务器端可用,不能被客户端访问。

    • js
      // 1. 在runtimeConfig 中定义环境变量
      runtimeConfig: {
        public: {
          apiUrl: process.env.API_URL,
          xxx: 'http://baidu.com'
        },
        yyy: 'yyy',
        zzz: 'zzz'
      },
      js
      // 2. 访问环境变量:useRuntimeConfig()
      const config = useRuntimeConfig()
      
      // 在客户端
      if(process.client) {
      	const apiUrl = config.public.apiUrl
      }
      
      // 在服务器端
      if(process.server) {
      	const apiUrl = config.public.apiUrl
      	const secret = config.yyy
      }

定义环境变量的方式:

方式一:在nuxt.config.ts中配置runtimeConfig

image-20240911152127865

访问环境变量:

image-20240911152140048

方式二:在.env中配置环境变量

可以通过.env 文件中的环境变量来覆盖runtimeConfig中的配置,优先级:.env > runtimeConfig

  • .env的变量会添加到 process.env 中,符合规则的会覆盖runtimeConfig 的变量。
  • .env一般用于某些终端启动应用时动态指定配置,不区分dev和pro环境。

注意:

  • 注意常量写法和驼峰写法之间的对应关系:

    • NUXT_APP_KEY - appKey

    • NUXT_PUBLIC_BASE_URL - public.baseURL

    • image-20240926101647264

  • .env中定义的环境变量必须在 nuxt.config 中定义。这样可以确保任意的环境变量不会暴露给应用程序代码。

获取.env文件中的环境变量:

和方式一一样,也是通过 useRuntimeConfig() 获取环境变量。

注意: 无法通过 process.env 获取。可能需要 dotenv 插件。

appConfig
  • appConfig{ 自定义 },应用配置,定义在构建时确定的公共变量,如:theme。

    • 注意: 配置会和app.config.ts配置合并。优先级: app.config.ts > appConfig

    • 注意: 前后端都可以访问配置项。

    • js
      export default defineNuxtConfig({
        appConfig: {
          siteName: 'My Awesome Site',
          apiBase: process.env.API_BASE_URL || 'https://api.example.com'
        }
      })
    • js
      // 访问配置:useAppConfig()
      const appConfig = useAppConfig()
      
      console.log(appConfig.siteName) // 输出: My Awesome Site
      console.log(appConfig.apiBase)   // 输出: https://api.example.com

抽取配置到app.config.ts

创建app.config.ts文件,并配置如下:

image-20240926110113546

app
  • app{baseURL, head},应用相关的配置,如头部信息、全局样式等。

    • baseURLstring,定义应用的基础 URL,通常用于处理相对路径。

    • buildAssetsDirstring,用于自定义构建生成的静态资源的目录。

    • cdnURLstring,用于指定 CDN(内容分发网络)的基本 URL,这样你可以将静态资源托管在 CDN 上,提高加载速度。

    • head{title, meta, link, style, script},给每个页面上设置 head 信息,也支持 useHead 配置和内置组件。

      • titlestring,标题。

      • meta[{charset},{ name, content}],元数据。

        • {charset}:``,字符编码。
        • { name, content}:``,
      • link[{rel, href}],外链样式。

      • style[{children, type}],样式。

      • script[{src, body?}],JS脚本。

        • src:``,script连接地址。
        • body?boolean是否将script添加到body标签中。
    • js
        app: {
          baseURL: '/my-app/',
          buildAssetsDir: 'static/assets/', // 自定义静态资源目录
          cdnURL: 'https://cdn.example.com/', // 替换为你的CDN地址
          head: {
            meta: [
              // <meta name="viewport" content="width=device-width, initial-scale=1">
              { name: 'viewport', content: 'width=device-width, initial-scale=1' }
            ],
          script: [
            // <script src="https://myawesome-lib.js"></script>
            { src: 'https://awesome-lib.js' }
          ],
          link: [
            // <link rel="stylesheet" href="https://myawesome-lib.css">
            { rel: 'stylesheet', href: 'https://awesome-lib.css' }
          ],
          // please note that this is an area that is likely to change
          style: [
            // <style type="text/css">:root { color: red }</style>
            { children: ':root { color: red }', type: 'text/css' }
          ],
          noscript: [
            // <noscript>JavaScript is required</noscript>
            { children: 'JavaScript is required' }
          ]
        }
      }

应用:

  • 可以在app选项中做SEO优化配置。

添加app配置的方式:

优先级内置组件 > useHead() > nuxt.config.ts

方式一: 使用useHead()钩子函数动态添加app配置项。

  • 如果在app.vue中使用useHead()会在项目全局起作用
  • 如果在某个vue文件中使用,则只会在该页面起作用

image-20240926153506061

方式二: 使用<Head><Meta><Style><Link><Script>这些内置组件添加app配置项。

image-20240926154325462

方式三:nuxt.config.ts配置的app配置项中设置。

app.config

app.config.ts用于公开在构建时确定的公共变量

注意:

  • app.config.ts配置文件中的选项不能使用 env 环境变量来覆盖,与runtimeConfig不同。
  • 不要存放秘密或敏感信息在 app.config.ts文件中,该文件是客户端公开

配置: 使用辅助函数 defineAppConfig() 提供代码提示

js
export default defineAppConfig({
  title: 'Hello Nuxt',
  theme: {
    dark: true,
    colors: {
      primary: '#ff0000'
    }
  }
})

访问配置:

js
// pages/index.vue
const appConfig = useAppConfig()

console.log(appConfig.theme.dark)

应用场景:

  • 全局常量:用于存放网站名称、主题色等不变的全局信息。
  • API 配置:方便管理 API 的基础 URL,便于调用。
  • 主题设置:可以集中管理主题相关的配置,比如颜色、字体等。
  • 功能开关:可以用于管理不同环境下的功能开关。

runtimeConfig 与 app.config

runtimeConfig 和 app.config 都用于向应用程序公开变量。要确定是否应该使用其中一种,以下是一些指导原则:

  • runtimeConfig:定义环境变量,比如:运行时需要指定的私有或公共 token。
  • app.config:定义公共变量,比如:在构建时确定的公共 token、网站配置。

image-20240911152223144

内置组件

Nuxt3 框架也提供一些内置的组件,常用的如下:

  • SEO组件: Html、Body、Head、Title、Meta、Style、Link、NoScript、Base
  • NuxtWelcome:欢迎页面组件,该组件是 @nuxt/ui 的一部分
  • NuxtLayout:是 Nuxt 自带的页面布局组件
  • NuxtPage:是 Nuxt 自带的页面占位组件
    • 需要显示位于目录中的顶级或嵌套页面 pages/
    • 是对 router-view 的封装
  • ClientOnly:该组件中的默认插槽的内容只在客户端渲染。而 fallback 插槽的内容只在服务器端渲染。
  • NuxtLink:是 Nuxt 自带的页面导航组件
    • 是 Vue Router<RouterLink>组件 和 HTML<a>标签的封装。
  • 等等

NuxtPage

NuxtPage:是 Nuxt 自带的页面占位组件<NuxtPage> 是对 Vue Router 的 <RouterView> 组件的封装。

1、在app.vue中使用占位组件<NuxtPage>

image-20240926163205783

2、在/pages/目录下创建组件home.vueindex.vue

3、直接输入路由地址:localhost:3000访问index.vuelocalhost:3000/home访问home.vue

image-20241007145501170

ClientOnly

ClientOnly:该组件中的默认插槽的内容只在客户端渲染。而 fallback 插槽的内容只在服务器端渲染

加载过程中显示fallback渲染的内容,等加载完毕就会用客户端渲染的内容替换fallback渲染的内容。

  • ClientOnly(),只在客户端渲染其插槽内容。
    • 属性
    • fallback:``,渲染占位
    • fallback-tag:``,渲染占位标签
    • 插槽
    • fallback:``,指定在服务器端显示的内容。

示例:

html
    <ClientOnly fallback-tag="span" fallback="加载评论中...">
      <!-- 这将在客户端渲染 -->
        
      <template #fallback>
        <!-- 这将在服务器端渲染 -->
        <p>加载评论中...</p>
      </template>
    </ClientOnly>

NuxtLink(),用来实现页面的导航。

  • 属性:
  • tostring,指定要导航的目标路径。支持路由路径路由对象URL
  • hrefstring,to的别名。
  • active-class默认:nuxt-link-active,激活链接的类名。
  • target_blank | _self |_parent |_top,与普通 <a> 标签相同,指定链接打开方式。

全局样式

手动导入

依赖包:

  • sass
    • 安装:pnpm i sass -D

基本使用:

1、在.css.scss文件中编写样式

image-20241007152247143

2、在nuxt.config.tscss中配置全局样式

image-20240926172444853

3、此时可以在组件中直接使用全局样式。

使用变量或混入:

1、在.scss文件中编写变量或混入

image-20240926171347604

2、在全局或局部组件中引入.scss文件并使用变量或混入

方式一:使用@import引入

  • 全局组件

    image-20240926171631622

  • 局部组件

    image-20240926171506474

方式二:使用@use引入(推荐

image-20240926171936036

▸自动导入

1、在.css.scss文件中编写样式

2、在nuxt.config.tsvite中配置全局样式

注意: 此处导入的文件和css配置项中导入的文件不能重复。

js
export default defineNuxtConfig({
  css: ['~/assets/css/main.css'],
    
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          // 在每个 SCSS 文件的开头自动引入多个scss文件。
          additionalData: `
            @use "@/assets/styles/global.scss" as *;
            @use "@/assets/styles/variables.scss" as *;
            @use "@/assets/styles/mixins.scss" as *;
          `
        }
      }
    }
  }
})

3、此时可以在组件中直接使用全局样式。

资源导入

public目录

public目录用作应用程序的公共服务器,用于存放在应用程序的指定URL下公开访问的静态资源。

public/img/ 目录中引用一个图像文件,该文件可通过静态URL /img/nuxt.png 访问:

html
<template>
  <img src="/img/nuxt.png" alt="Discover Nuxt 3" />
</template>

静态的 URL /img/nuxt.png 也支持在背景中使用:

html
<template>
    <div class="box"></div>
</template>
<style lang="scss">
    .box {
        width: 200px;
        height: 150px;
        background-image: url(/img/nuxt.png);
    }
</style>

assets目录

assets目录经常用于存放如样式表字体SVG 的资源

可以使用 ~/assets/ 路径引用位于 assets 目录中的资产文件

html
<template>
  <img src="~/assets/img/nuxt.png" alt="Discover Nuxt 3" />
</template>

~/assets/ 路径也支持在背景中使用

html
<template>
    <div class="box"></div>
</template>
<style lang="scss">
    .box {
        width: 200px;
        height: 150px;
        background-image: url(~/assets/img/nuxt.png);
    }
</style>

注意: 同样支持@/assets/base64的写法。

html
<img src="@/assets/img/nuxt.png" alt="Discover Nuxt 3" />

<img src="base64;type=image/png xxx" alt="Discover Nuxt 3" />

字体图标

1、将字体图标存放在 assets 目录下

image-20240926180407911

2、字体文件可以使用 ~/assets/ 路径引用。

image-20240926180425116

3、在 nuxt.config 配置文件中导入全局样式

image-20240926180526079

4、在页面中就可以使用字体图标了

image-20240926180656587

新建页面

Nuxt 项目中的页面是在 pages 目录下创建的。

pages 目录创建的页面,Nuxt 会根据该页面的目录结构和其文件名来自动生成对应的路由

页面路由也称为文件系统路由器(file system router),路由是 Nuxt 的核心功能之一。

手动创建页面:

  • 1.创建页面文件,比如: pages/index.vue
  • 2.将<NuxtPage />内置组件添加到 app.vue
  • 3.页面如果使用 scss 那么需要安装:npm i sass -D

image-20240911152411388

命令行创建页面:

语法:

sh
pnpm dlx nuxi add page <path>

说明:

  • pnpm dlx nuxi:相当于npx nuxi
  • add page:创建页面的命令
  • <path>:要添加的页面路径,可以是相对路径。有以下写法:
    • about:创建pages/about.vue页面。
    • about/index:创建pages/about/index.vue页面。
    • about/[id]
    • about-[role]/[id]

示例:

sh
npx nuxi add page home # 创建 home 页面
npx nuxi add page detail/[id] # 创建 detail 页面
npx nuxi add page user-[role]/[id] # 创建 user 页面

image-20240911152419264

导航

组件导航

NuxtLink(),用来实现页面的导航。

  • 属性:

  • tostring | {path, query | params},指定要导航的目标路径。支持路由路径路由对象URL

  • hrefstring,to的别名。

  • active-class默认:nuxt-link-active,激活链接的类名。

  • target_blank | _self |_parent |_top,与普通 <a> 标签相同,指定链接打开方式。

  • replaceboolean,如果设置为 true,则在导航时使用替换模式,这意味着不会在历史记录中添加新条目。

  • prefetchboolean,如果设置为 true,则在鼠标悬停链接时预取该页面的资源,以加快加载速度。

  • html
    <template>
      <nav>
        <NuxtLink to="/home">Home</NuxtLink>
        <NuxtLink :to="{path: '/home', query: {id: 10}}">Home</NuxtLink>
        <NuxtLink to="https://www.baidu.com">Home</NuxtLink>
          
        <NuxtLink href="/home">Home</NuxtLink>
          
        <NuxtLink to="/about" active-class="active">About</NuxtLink>
          
        <NuxtLink to="/profile" target="_blank">Profile</NuxtLink>
          
        <NuxtLink to="/profile" replace>Profile</NuxtLink>
          
        <NuxtLink to="/about" prefetch>About</NuxtLink>
          
        <!-- 使用a标签页面会刷新 -->
        <a href="/more">More</a>
      </nav>
    </template>

<NuxtLink> 是 Nuxt 内置组件,是对 <RouterLink> 的封装,用来实现页面的导航

该组件底层是一个<a>标签,因此使用 a + href 属性也支持路由导航。但是用 a 标签导航会有触发浏览器默认刷新事件,而 NuxtLink 不会,NuxtLink 还扩展了其它的属性和功能。

应用 Hydration 后(已激活,可交互),页面导航会通过前端路由来实现。这可以防止整页刷新

当然,手动输入 URL 后,点击刷新浏览器也可导航,这会导致整个页面刷新。

image-20240911152433425

编程导航

  • navigateTo()(to , options?),用于进行编程导航的函数。非常适合需要在事件处理程序生命周期钩子中进行导航的场景。

    • tostring | {path, query | params},目标路由的路径,可以是一个字符串(如 /about),也可以是一个对象,包含更复杂的路由信息。

    • options?{replace, external},用于控制导航的行为。

      • replaceboolean默认:false,为 true 时会替换当前路由页面。
      • externalboolean默认:false,为 true 时允许导航到外部连接。
    • 返回:

    • promisePromise

    • js
      // to:字符串路径
      navigateTo('/about');
      
      // to:对象路径-query
      navigateTo({
        path: '/home',
        query: { name: 'tom' }
      });
      
      // to:对象路径-params
      navigateTo({
        path: '/posts/[id]',
        params: { id: postId }
      });
      
      // repalce选项:替换当前历史记录条目
      navigateTo('/home', { replace: true });
      
      // external选项:跳转到外部链接(必须设置external:true)
      navigateTo('https://www.baidu.com', { external: true })
  • useRouter()(),用于访问 Vue Router 实例。可以在组件中实现导航功能

    • routerRouter,提供了一系列方法和属性,以便于进行路由导航和获取当前路由信息。

    • js
      import { useRouter } from 'vue-router';
      
      const router = useRouter();
  • router.push()(to),导航到一个新的路由。建议用 navigateTo ,支持性更好。

    • tostring | {path, query | params}

    • js
      router.push('/about');
  • router.replace()(to),替换当前的路由,而不是添加新条目。建议用 navigateTo ,支持性更好。

    • tostring | {path, query | params}

    • js
      router.replace('/home');
  • router.go()(count),前进或后退指定数量的历史记录条目。

    • countnumber | -number

    • js
      router.go(-1); // 后退一步
  • router.back()(),回到上一个路由。

    • js
      router.back();
  • router.forward()(),页面前进。

    • js
      router.forward()
  • router.beforeEach()((to, from, next) => void),注册全局前置守卫(通常在应用初始化时使用)。

    • to:``,

    • from:``,

    • next:``,

    • js
      router.beforeEach((to, from, next) => {
        // 逻辑
        next();
      });
  • router.afterEach()((to, from, next) => void),注册全局后置守卫。

    • to:``,

    • from:``,

    • next:``,

    • js
      router.afterEach((to, from, next) => {
        // 逻辑
        next();
      });

navigateTo():

Nuxt3 除了可以通过<NuxtLink>内置组件来实现导航,同时也支持编程导航:navigateTo()

通过编程导航,在应用程序中就可以轻松实现动态导航了,但是编程导航不利于 SEO

navigateTo 函数在服务器端客户端可用,也可以在插件、中间件中使用,也可以直接调用以执行页面导航,例如:

  • 当用户触发该 goToProfile()方法时,我们通过 navigateTo 函数来实现动态导航。
  • 建议: goToProfile 方法总是返回 navigateTo 函数(该函数不需要导入)或 返回异步函数

image-20240911152444836

useRouter():

Nuxt3 中的编程导航除了可以通过 navigateTo 来实现导航,同时也支持 useRouter() ( 或 Options API 的 this.$router )

image-20240911152500451

路由

动态路由

Nuxt3 和 Vue 一样,也是支持动态路由的,只不过在 Nuxt3 中,动态路由也是根据目录结构和文件的名称自动生成。

动态路由语法:

  • 页面组件目录 或 页面组件文件都 支持 [ ] 方括号语法
  • 方括号里编写动态路由的参数。

例如,动态路由 支持如下写法:

  • pages/detail/[id].vue -> /detail/:id
  • pages/detail/user-[id].vue -> /detail/user-:id
  • pages/detail/[role]/[id].vue -> /detail/:role/:id
  • pages/detail-[role]/[id].vue -> /detail-:role/:id

注意事项:

  • 动态路由 和 index.vue 不能同时存在, Next.js 则可以

image-20240911152514589

image-20240911152523455

路由参数

动态路由参数

  • 1.通过 [] 方括号语法定义动态路由,比如:/detail/[id].vue
  • 2.页面跳转时,在 URL 路径中传递动态路由参数,比如:/detail/10010
  • 3.目标页面通过 route.params 获取动态路由参数

查询字符串参数

  • 1.页面跳转时,通过查询字符串方式传递参数,比如:/detail/10010?name=liujun
  • 2.目标页面通过 route.query 获取查询字符串参数

image-20240911152536137

404 Page

捕获所有不配路由(即 404 not found 页面)

  • 通过在方括号内添加三个点 ,如:[...slug].vue 语法,其中 slug 可以是其它字符串。
  • 除了支持在 pages 根目录下创建,也支持在其子目录中创建。
  • Nuxt3 正式版不支持 404.vue 页面了,以前的候选版是支持的 404.vue,但是 Next.js 是支持。

image-20240911152549514

路由匹配规则

路由匹配需注意的事项

  • 预定义路由优先于动态路由,动态路由优先于捕获所有路由。请看以下示例:
    • 1.预定义路由:pages/detail/create.vue ➢ 将匹配 /detail/create
    • 2.动态路由:pages/detail/[id].vue ➢ 将匹配/detail/1, /detail/abc 等。 ➢ 但不匹配 /detail/create 、/detail/1/1、/detail/ 等
    • 3.捕获所有路由:pages/detail/[...slug].vue ➢ 将匹配 /detail/1/2, /detail/a/b/c 等。 ➢ 但不匹配 /detail 等

嵌套路由

Nuxt 和 Vue 一样,也是支持嵌套路由的,只不过在 Nuxt 中,嵌套路由也是根据目录结构和文件的名称自动生成。

编写嵌套路由步骤:

  • 1.创建一个一级路由,如:parent.vue
  • 2.创建一个与一级路由同名同级的文件夹,如: parent
  • 3.在 parent 文件夹下,创建一个嵌套的二级路由
    • 如:parent/child.vue, 则为一个二级路由页面
    • 如: parent/index.vue 则为二级路由默认的页面
  • 4.需要在 parent.vue 中添加 NuxtPage 路由占位

image-20240911152609332

image-20240911152614587

路由中间件(middleware)

Nuxt 提供了一个可定制的 路由中间件,用来监听路由的导航,包括:局部和全局监听(支持再服务器和客户端执行)

路由中间件分为三种:

  • 匿名(或内联)路由中间件
    • 在页面中使用 definePageMeta 函数定义,可监听局部路由。当注册多个中间件时,会按照注册顺序来执行。
  • 命名路由中间件
    • 在 middleware 目录下定义,并会自动加载中间件。命名规范 kebab-case)
  • 全局路由中间件(优先级比前面的高,支持两端)
    • 在 middleware 目录中,需带.global 后缀的文件,每次路由更改都会自动运行。

image-20240911152633942

image-20240911152645202

路由验证( validate )

Nuxt 支持对每个页面路由进行验证,我们可以通过 definePageMeta 中的 validate 属性来对路由进行验证。

  • validate 属性接受一个回调函数,回调函数中以 route 作为参数
  • 回调函数的返回值支持:
    • 返回 bool 值来确定是否放行路由 ➢ true 放行路由 ➢ false 默认重定向到内置的 404 页面
    • 返回对象 ➢ { statusCode:401 } // 返回自定义的 401 页面,验证失败

路由验证失败,可以自定义错误页面:

  • 在项目根目录(不是 pages 目录)新建 error.vue

image-20240911152705706

image-20240911152656539

布局(Layout)

Layout 布局是页面的包装器,可以将多个页面共性东西抽取到 Layout 布局 中。

  • 例如:每个页面的页眉和页脚组件,这些具有共性的组件我们是可以写到一个 Layout 布局中。

Layout 布局是使用<slot>组件来显示页面中的内容

Layout 布局有两种使用方式:

  • 方式一:默认布局
    • 在 layouts 目录下新建默认的布局组件,比如:layouts/default.vue
    • 然后在 app.vue 中通过<NuxtLayout>内置组件来使用
  • 方式二:自定义布局(Custom Layout)
    • 继续在 layouts 文件夹下新建 Layout 布局组件,比如: layouts/custom-layout.vue
    • 然后在 app.vue 中给<NuxtLayout>内置组件 指定 name 属性 的值为:custom-layout ➢ 也支持在页面中使用 definePageMeta 宏函数来指定 layout 布局

image-20240911152717550

渲染模式

浏览器 和 服务器都可以解释 JavaScript 代码,都可以将 Vue.js 组件呈现为 HTML 元素。此过程称为渲染。

  • 在客户端将 Vue.js 组件呈现为 HTML 元素,称为:客户端渲染模式
  • 在服务器将 Vue.js 组件呈现为 HTML 元素,称为:服务器渲染模式

而 Nuxt3 是支持多种渲染模式,比如:

  • 客户端渲染模式(CSR): 只需将 ssr 设置为 false
  • 服务器端渲染模式(SSR):只需将 ssr 设置为 true
  • 混合渲染模式(SSR | CSR | SSG | SWR):需在 routeRules 根据每个路由动态配置渲染模式(beta 版本)

image-20240911152730827

image-20240911152738420

Nuxt 插件(Plugins)

Nuxt3 支持自定义插件进行扩展,创建插件有两种方式:

  • 方式一:直接使用 useNuxtApp() 中的 provide(name, vlaue) 方法直接创建,比如:可在 App.vue 中创建
    • useNuxtApp 提供了访问 Nuxt 共享运行时上下文的方法和属性(两端可用):provide、hooks、callhook、vueApp 等
  • 方式二:在 plugins 目录中创建插件(推荐)
    • 顶级和子目录 index 文件写的插件会在创建 Vue 应用程序时会自动加载和注册
    • .server 或 .client 后缀名插件,可区分服务器端或客户端,用时需区分环境

在 plugins 目录中创建插件

  • 1.在 plugins 目录下创建 plugins/price.ts 插件
  • 2.接着 defineNuxtPlugin 函数创建插件,参数是一个回调函数
  • 3.然后在组件中使用 useNuxtApp() 来拿到插件中的方法

注意事项:

  • 插件注册顺序可以通过在文件名前加上一个数字来控制插件注册的顺序
    • 比如:plugins/1.price.ts 、plugins/2.string.ts、plugins/3.date.ts

image-20240911152752332

image-20240911152802298

生命周期

App Lifecycle Hooks

监听 App 的生命周期的 Hooks:

  • App Hooks 主要可由 Nuxt 插件 使用 hooks 来监听 生命周期,也可用于 Vue 组合 API 。
  • 但是,如在组件中编写 hooks 来监听,那 create 和 setup hooks 就监听不了,因为这些 hooks 已经触发完了监听。

语法:nuxtApp.hook(app:created, func)

image-20240911152822455

组件生命周期

客户端渲染

image-20240911152833536

服务器端渲染

  • beforeCreate -> setup
  • created

image-20240911152844344

异步请求

获取数据

在 Nuxt 中数据的获取主要是通过下面 4 个函数来实现(支持 Server 和 Client ):

  • 1.useAsyncData(key, func):专门解决异步获取数据的函数,会阻止页面导航。
    • 发起异步请求需用到 $fetch 全局函数(类似 Fetch API) ➢ $fetch(url, opts)是一个类原生 fetch 的跨平台请求库
  • 2.useFetch(url, opts):用于获取任意的 URL 地址的数据,会阻止页面导航
    • 本质是 useAsyncData(key, () => $fetch(url, opts)) 的语法糖。
  • 3.useLazyFetch(url, opts):用于获取任意 URL 数据,不会阻止页面导航
    • 本质和 useFetch 的 lazy 属性设置为 true 一样
  • 4.useLazyAsyncData(key, func):专门解决异步获取数据的函数。 不会阻止页面导航
    • 本质和 useAsyncData 的 lazy 属性设置为 true 一样

注意事项:

  • 这些函数只能用在 setup or Lifecycle Hooks 中。

image-20240911152857560

image-20240911152903030

image-20240911152908081

useFetch vs axios

获取数据 Nuxt 推荐使用 useFetch 函数,为什么不是 axios ?

  • useFetch 底层调用的是$fetch 函数,该函数是基于 unjs/ohmyfetch 请求库,并与原生的 Fetch API 有者相同 API
  • unjs/ohmyfetch 是一个跨端请求库: A better fetch API. Works on node, browser and workers
    • 如果运行在服务器上,它可以智能的处理对 API 接口的直接调用。
    • 如果运行在客户端行,它可以对后台提供的 API 接口 正常的调用(类似 axios),当然也支持第三方接口的调用
    • 会自动解析响应和对数据进行字符串化
  • useFetch 支持智能的类型提示和智能的推断 API 响应类型。
  • 在 setup 中用 useFetch 获取数据,会减去客户端重复发起的请求。

useFetch(url, options)语法

  • 参数
    • url: 请求的路径
    • options:请求配置选项 ➢ method、query ( 别名 params )、body、headers、baseURL ➢ onRequest、 onResponse、lazy....
  • 返回值: data, pending, error, refresh

image-20240911152920968

useFetch 的封装

封装 useFetch 步骤

  • 1.定义 HYRequest 类,并导出
  • 2.在类中定义 request、get、post 方法
  • 3.在 request 中使用 useFetch 发起网络请求
  • 4.添加 TypeScript 类型声明

image-20240911152934257

Server API

Nuxt3 提供了编写后端服务接口的功能,编写服务接口可以在 server/api 目录下编写

比如:编写一个 /api/homeinfo 接口

  • 1.在 server/api 目录下新建 homeinfo.ts
  • 2.接在在该文件中使用 defineEventHandler 函数来定义接口(支持 async)
  • 3.然后就可以用 useFetch 函数轻松调用: /api/homeinfo 接口了

image-20240911152948244

image-20240911152957461

Pinia

全局状态共享

Nuxt 跨页面、跨组件全局状态共享可使用 useState(支持 Server 和 Client ):

  • useState<T>(init?: () => T | Ref<T>): Ref<T>
  • useState<T>(key: string, init?: () => T | Ref<T>): Ref<T>
  • 参数:
    • init:为状态提供初始值的函数,该函数也支持返回一个 Ref 类型
    • key: 唯一 key,确保在跨请求获取该数据时,保证数据的唯一性。为空时会根据文件和行号自动生成唯一 key
  • 返回值:Ref 响应式对象

useState 具体使用步骤如下:

  • 1.在 composables 目录下创建一个模块,如: composables/states.ts
  • 2.在 states.ts 中使用 useState 定义需全局共享状态,并导出
  • 3.在组件中导入 states.ts 导出的全局状态

useState 注意事项:

  • useState 只能用在 setup 函数 和 Lifecycle Hooks 中
  • useState 不支持 classes, functions or symbols 类型,因为这些类型不支持序列化

image-20240911153014463

Nuxt3 集成 Pinia

安装依赖

  • npm install @pinia/nuxt –-save
    • @pinia/nuxt 会处理 state 同步问题,比如不需要关心序列化或 XSS 攻击等问题
  • npm install pinia –-save
    • 如有遇到 pinia 安装失败,可以添加 --legacy-peer-deps 告诉 NPM 忽略对等依赖并继续安装。或使用 yarn

Nuxt 应用接入 Pinia

  • 在 nuxt.config 文件中添加: modules: [‘@pinia/nuxt‘] ,如下图所示:

image-20240911153027343

Pinia 使用步骤

Pinia 使用步骤:

  • 1.在 store 文件夹中定义一个模块,比如:store/counter.ts
  • 2.在 store/counter.ts 中使用 defineStore 函数来定义 store 对象
  • 3.在组件中使用定义好的 store 对象

image-20240911153041827

image-20240911153047859

useState vs Pinia

Nuxt 跨页面、跨组件全局状态共享,既可以使用 useState,也可以使用 Pinia,那么他们有什么异同呢?

它们的共同点:

  • 都支持全局状态共享,共享的数据都是响应式数据
  • 都支持服务器端和客户端共享

但是 Pinia 比 useState 有更多的优势,比如:

  • 开发工具支持(Devtools)
    • 跟踪动作,更容易调试
    • store 可以出现在使用它的组件中
    • ....
  • 模块热更换
    • 无需重新加载页面即可修改 store 数据
    • 在开发时保持任何现有状态
  • 插件:可以使用插件扩展 Pinia 功能
  • 提供适当的 TypeScript 支持或自动完成

项目:mr-oppo

项目介绍

OPPO 手机商城

image-20240911153127538

项目需安装的依赖

样式

  • npm install normalize.css –save
  • npm install sass –-save-dev

Pinia

  • npm install @pinia/nuxt --save
  • npm install pinia –save --legacy-peer-deps

Element Plus

  • npm install element-plus –save
  • npm install unplugin-element-plus --save-dev

安装 Element Plus 2

Element Plus 官网:https://element-plus.org/zh-CN/guide/quickstart.html

安装 Element Plus 的具体步骤:

  • 第一步:
    • npm install element-plus --save
    • npm install unplugin-element-plus --save-dev
  • 第二步:
    • 配置 Babel 对 EP 的转译
    • 配置自动导入样式
  • 第三步:
    • 在组件中导入组件,并使用

注意事项:目前 Nuxt3 暂时还不支持 EP 组件自动导包,等后续 EP 的 module

image-20240911153143796

image-20240911153150066

购买-阿里云服务器

阿里云服务器购买地址:https://aliyun.com/

  • 1.打开控制台
  • 2.菜单找到:云服务器 ECS
  • 3.创建我们 ECS
  • 4.服务器的配置
    • CentOS 7.9 / 64
    • 2cpu 4G
  • 5.配置安全组
  • 6.系统配置,自定义密码
  • 7.确认订单,创建实例

image-20240911153202733

连接-阿里云服务器

VS Code 安装:Remote SSH 插件

image-20240911153214818

Remote SSH 连接远程服务器

image-20240911153223136

image-20240911153228309

image-20240911153233416

安装 Node 和 PM2

安装 Node

  • yum install nodejs ( 16.17.0 )
  • yum install npm ( 8.15.0 )

认识 PM2(Process Manager)

  • PM2 是一个守护进程管理器, 它将帮助管理和保持你的在线应用程序
  • 更简单的理解:负责管理 Node、Python 等程序,并能让程序一直保持在后台运行

安装 PM2

  • npm install –g pm2 ( 5.2.2 )

管理 Node 版本(可选)

  • npm install –g n
  • n --version # 查看版本

image-20240911153246157

image-20240911153252154

PM2 常用命令

PM2 常用命令和配置文件

image-20240911153303371

image-20240911153314104

项目打包和部署

项目打包

  • 执行 npm run build , 生成的.output 文件夹就是部署产物(目前不支持中文路径)
  • 执行 npm run preview 本地预览效果

使用 Node 部署

  • 运行:node .output/server/index.mjs
  • 指定端口:PORT=8888 node .output/server/index.mjs
    • PORT:是动态添加的环境变量

使用 PM2 部署(推荐)

  • pm2 init simple # 自动生成 ecosystem 配置文件
  • pm2 start ecosystem.config.js # 启动应用
    • instances:指定启动实例(进程)的个数
    • exec_mode:运行的模式:cluster 模式和 fork 模式(默认)

image-20240911153346412