13.3 nuxt基本知识学习

101 阅读6分钟

1. 参考学习链接

https://github.com/codprincess/j-book-demo.git

2. 创建 demo 项目

npx nuxi init nuxt4-demo

✔ Which package manager would you like to use? pnpm
✔ Initialize git repository? No
✔ Would you like to install any of the official modules? No

3. 启动项目

cd nuxt4-demo
pnpm dev

4. 创建项目结构

在 app 目录下创建 pages 目录,增加 about.vue,home.vue 文件,此时修改 app.vue 文件

<template>
  <div>
    <!-- <NuxtRouteAnnouncer />
    <NuxtWelcome /> -->
    <NuxtPage />
  </div>
</template>

此时查看 http://localhost:3001/ 找不到页面,因为没有配置路由,所以需要配置路由 page 目录下创建 index.vue 文件

5.配置 Ant design Vue

1. 1 安装依赖包

pnpm add -D @ant-design-vue/nuxt

在 nuxt.config.ts 中添加 ant-design-vue

export default defineNuxtConfig({
  modules: ['@ant-design-vue/nuxt'],
})

1.2.按需配置

pnpm install unplugin-vue-components -D

// TODO 待完善 // TODO 主题配置待完善

2. 1 安装依赖包

pnpm add ant-design-vue

[plugin:vite:import-analysis] Failed to resolve import "ant-design-vue/es/button/style/css" from "app/pages/index.vue". Does the file exist?
解决方案 blog.csdn.net/a1308003218…

// https://nuxt.com/docs/api/configuration/nuxt-config

import Components from "unplugin-vue-components/vite";
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";

export default defineNuxtConfig({
  compatibilityDate: "2025-07-15",
  devtools: { enabled: true },
  // modules: ['@ant-design-vue/nuxt'],
  vite: {
    plugins: [
      // 按需引⼊组件
      Components({
        resolvers: [AntDesignVueResolver({ importStyle: false })],
      }),
    ],
    // ssr
    ssr: {
      noExternal: ["ant-design-vue"],
    },
  },
});

在需要组件中直接引入看效果

<template>
  <!-- vue3页面 -->
  <div>根节点页面 </div>
  <a-button type="primary">按钮</a-button>
</template>

3.1 添加子组件

创建 component 组件,在 pages 目录下创建 components 目录,在创建 Demo.vue 组件

直接在主页面引用即可,nuxt 自动实现了引入 components 下的子组件

6. 动态路由

如果你想要创建⼀个名为 user 的⻚⾯,可以在 pages/user ⽬录下创建⼀个名为 [id]. vue 的⽂件 呈现⼀个 标记,其中 href 属性设置为⻚⾯的路由。

<template>
  <h1>User {{ route.params.id }}</h1>
  <h1>User-query {{ route.query.id }}</h1>
  <a-button type="primary">
    <NuxtLink to="/about">NuxtLink跳转About</NuxtLink>
  </a-button>
  <br />
  <a-button type="primary" @click="goToRouter"> 路由方法跳转About </a-button>
</template>
<script setup>
// import { useRoute } from "nuxt/app";
const route = useRoute();
const router = useRouter();
const goToRouter = () => {
  router.push("/about");
};
console.log("route", route);
</script>

7.Nuxt 3 路由中间件

Nuxt 3 中提供了⼀个路由中间件,它允许在路由跳转前或者路由跳转后执⾏⼀些代码,例如进⾏⻚⾯访 问权限的验证、记录⽤户的访问记录等等。 我们在 pages 目录下 middleware/ 创建⼀个 auth.js 中间件

  1. 具名的路由中间件
export default function ({ store, redirect }) {
  // 判断⽤户是否已经登录
  // 假设
  console.log("路由中间件执行了");
  let authUser = false;
  if (!authUser) {
    return navigateTo("/login");
  }
}

使用中间件,在对应的页面中添加 middleware: "auth"

definePageMeta({
  middleware: "auth",
});
  1. 全局路由中间件 middleware/_**.global.js _/
export default defineNuxtRouteMiddleware((to, from) => {
  console.log(`1.全局路由中间件 to: ${to.path}, from: ${from.path}`);
});

3.匿名(或内联)路由中间件

definePageMeta({
  middleware: [
    "auth",
    "auth-other",
    defineNuxtRouteMiddleware(() => {
      console.log("4.匿名(或内联)路由中间件执行了");
      let authUser = false;
      if (!authUser) {
        return navigateTo("/home");
      }
    }),
  ],
});

8.插件 plugins-公共方法

只有在 plugins/ ⽬录的顶层的⽂件(或任何⼦⽬录中的索引⽂件)才会被注册为插件

plugins
 | - myPlugin.ts
 | - myOtherPlugin
 | |-- supportingFile.ts
 | |-- componentToRegister.vue
 | |-- index.ts

//plugins/myPlugin.ts
export default defineNuxtPlugin((nuxtApp) => {
  return {
    //⾃动提供辅助函数,返回辅助函数
    provide: {
      myPlugin: (msg: string) => `Hello ${msg}!`,
    },
  };
});

9.Ant ⾮组件模块处理

之前我们按需引⼊蚂蚁框架组件时,官⽅提示⾮组件不能直接使⽤。我们需要⼿动引⼊

//pages/index.vue
<template>
...
<a-button type="primary" @click="info">消息弹框</a-button>
</template>
<script setup>
...
import 'ant-design-vue/es/message/style/css';
import {message} from "ant-design-vue";
const info = () => {
 message.info('这是⼀个消息')
}
</script>

我们不想每次使⽤都要⼿动引⼊,我们可以将其封装成插件。在 plugins/ ⽬录下创建 antPlugin.ts ⽂件,

import 'ant-design-vue/es/message/style/css'
import 'ant-design-vue/es/notification/style/css'
import { message ,notification } from 'ant-design-vue';
export default defineNuxtPlugin(nuxtApp => {
 return {
 //⾃动提供辅助函数
 provide: {
 message: message,
 notification: notification
 }
 }
})

在使⽤的⻚⾯上:这样⼦我们就不⽤⼿动引⼊了

//pages/about.vue
<template>
...
<a-button type="primary" @click="info">消息弹框</a-button>
</template>
<script setup>
...
const { $message } = useNuxtApp()
const info = () => {
 $message.info('这是⼀个消息')
}
</script>

10. pina 安装和使用

1.安装

pnpm add pinia @pinia/nuxt

2.配置项

// nuxt.config.js

 modules: ['@pinia/nuxt'],

3.创建⼀个 store ,在 pages/store 文件夹下创建 myStore.ts

import { defineStore } from 'pinia'
export const useMyStore = defineStore('myStore',{
 state: () => ({
 counter: 1
 }),
 getters: {
 doubleCounter:(state) => state.counter * 2
 },
 actions: {
 add(){
 this.counter++
 }
 }
})

4.在页面中使用

在⻚⾯上使⽤


<template>
  <!-- vue3页面 -->
  <div>人生何处不相逢</div>
  引用子组件
  <demo />
  <NuxtLink
    :to="{ path: '/user/58', query: { msg: JSON.stringify(msg), id: 85 } }"
  >
    NuxtLink带参数跳转
  </NuxtLink>
  <h1>plugins-公共方法引用</h1>
  <div>
    {{ $myPlugin("world") }}
  </div>
  <h1>Ant⾮组件模块处理</h1>
  <a-button type="primary" @click="info">消息弹框</a-button>
  <h1>pina的使用</h1>
  <div>数量:{{ counter }} getter-数量:{{ doubleCounter }}</div>
  <a-button type="primary" @click="countAdd">数量+1</a-button>
</template>

<script lang="ts" setup>
// import "ant-design-vue/es/message/style/index";
// import { message } from "ant-design-vue";
import { storeToRefs } from "pinia";
import { useMyStore } from "./store/myStore";
const myStore = useMyStore();

definePageMeta({
  middleware: [
    "auth",
    "auth-other",
    defineNuxtRouteMiddleware(() => {
      console.log("4.匿名(或内联)路由中间件执行了");
      // let authUser = false;
      // if (!authUser) {
      //   return navigateTo("/home");
      // }
    }),
  ],
});
// 也可以在这⾥使⽤
const { $myPlugin } = useNuxtApp();
const msg = {
  id: 1,
  author: "hedy",
  book: "nuxt3 全栈学习",
};
// message弹框
const { $message } = useNuxtApp();

const info = () => {
  // message.info("这是⼀个消息");
  $message.info("这是⼀个消息");
};
// TODO pina store使用
const { counter, doubleCounter } = storeToRefs(myStore);
console.log("pina-myStore", counter, doubleCounter);

const countAdd = () => {
  myStore.add();
};
</script>

<style scoped></style>


5.持久话处理

// https://nuxt.com/docs/api/configuration/nuxt-config

import Components from "unplugin-vue-components/vite";
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";

export default defineNuxtConfig({
  compatibilityDate: "2025-07-15",
  devtools: { enabled: true },
  // modules: ['@ant-design-vue/nuxt'],
  vite: {
    plugins: [
      // 按需引⼊组件
      Components({
        resolvers: [AntDesignVueResolver({ importStyle: false })],
      }),
    ],
    // ssr
    ssr: {
      noExternal: ["ant-design-vue"],
    },
  },
  modules: ["@pinia/nuxt", "@pinia-plugin-persistedstate/nuxt"],
  piniaPersistedstate: {
    // 全局默认配置
    storage: "sessionStorage", // 可选 'localStorage' | 'sessionStorage' | 'cookies'
    cookieOptions: {
      // 如果选择 'cookies',可以配置 Cookie 选项
      maxAge: 3600, // 1 小时过期
      sameSite: "lax",
      secure: true, // 仅 HTTPS
    },
  },
});

缓存某一项的 store/myStore.js

import { defineStore } from "pinia";
export const useMyStore = defineStore("myStore", {
  state: () => ({
    counter: 1,
  }),
  getters: {
    doubleCounter: (state) => state.counter * 2,
  },
  persist: true,

  actions: {
    add() {
      this.counter++;
    },
  },
});

11.状态管理之 useState

11.1 共享状态

通过使用 auto-imported composables,我们可以定义全局类型安全状态并在整个应用中导入它们。 我们在项目根目录下面创建 composables/ 目录,用来放我们的状态。 创建 composables/states.ts :

export const useCounter = () => useState<number>('counter', () => 0)
export const useColor = () => useState<string>('color', () => 'pink')
<template>
  <!-- vue3页面 -->
  <div>恭喜发财-home</div>
  <h1>pina的使用</h1>
  <div>数量:{{ counter }} getter-数量:{{ doubleCounter }}</div>
  <a-button type="primary" @click="countAdd">数量+1</a-button></br>

    <h1>useState</h1>
   <div>颜色{{color}}</div>
  <a-button type="primary" @click="changeColor">颜色修改</a-button></br>
</template>

<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { useMyStore } from "./store/myStore";
const myStore = useMyStore();
const { counter, doubleCounter } = storeToRefs(myStore);
const countAdd = () => {
  myStore.add();
};
// useState使用
const color = useColor() // Same as useState('color')
//重新赋值
const changeColor = () => {
  const colors = ["red", "blue", "green", "pink", "yellow", "purple", "orange", "black", "white", "gray"];
  color.value = colors[Math.ceil(Math.random()*10)] || 'black';//像赋值普通ref一样给全局状态赋值
};
</script>

<style scoped></style>

12.useCookie 管理

Nuxt 3 提供了一个组合式函数 useCookie() 来让我们可以读写 Cookie。

const cookie = useCookie(name, options)

name : 对应的就是 cookie 的 key。 options : 设置多个 cookie 属性

  • maxAge : 指定 Max-Age 属性的值,单位是秒。如果没有设置,则这个 cookie 将会是 Session Only,意即网页关闭后就会消失。
  • expires : 指定一个 Date 物件来作为过期的时间,通常是要相容比较旧的浏览器做使用,如果 maxAge 与 expires 属性都有设定,则过期时间应该要设定为一样。
  • httpOnly : 是一个布尔值,默认为 false,当设置为 true 时,表示客户端的 JavaScript 将无法使用 document.cookie 来查看这个 cookie。通常是比较敏感或机密的讯息,如 Token 或 Session Id 会设 定为 true,只让浏览器发出请求时自动夹带。
  • secure : 是一个布尔值,默认为 false,当设置为 true 时浏览器得是 HTTPS 的加密传输协定的情境 下,才会自动夹带这个 cookie。
  • domain : 指定 cookie 可以适用的 Domain,通常会保持预设,表是适用于自己的 Domain 之下。默 认情况下,未设置任何域,大多数客户端将认为 cookie 仅适用于当前域。
  • path : 指定 cookie 适用的路径。
  • sameSite : 用于设定安全策略。
  • encode : 由于 cookie 的值只能使用有限的字元集,所以这个设置可以将 cookie 编码成合法的字串 值,默认的编码是使用 JSON.stringify+ encodeURIComponent()。
  • decode : cookie 会经过一个解码的过程,默认的解码是使用 decodeURIComponent+ destr。
  • default : 为一个函数,可以用于回传 cookie 的默认值,也可以是回传一个 Ref。

demo

<template>
 <div>
 <h1>Counter: {{ counter || '-' }}</h1>
 <button @click="counter = null">reset</button>
 <button @click="counter--">-</button>
 <button @click="counter++">+</button>
 </div>
</template>
<script setup>
const counter = useCookie('counter')
counter.value = counter.value || Math.round(Math.random() * 1000)
</script>

13.全局和局部样式

13.1 全局引入

静态资源一般放在 assets/ 目录下。我们在 assets/css/ 目录下创建 全局样式的文件 global.scss

//global.scss
.j-flex{
 display: flex;
}
.j-sb{
 justify-content: space-between;
}
.f-24 {
  font-size: 24px;
}
.f-36 {
  font-size: 36px;
}

在 nuxt.config.ts 中配置:

export default defineNuxtConfig({
 css: [
 '~/assets/css/global.css'
 ],
 //...
})

13.2 局部样式文件

局部样式我们可以直接在页面上写

13.3 改成 scss

下载依赖

pnpm i sass-embedded -D

14.数据获取 useFetch()

useFetch() 是 Nuxt3 中的一个新的 API ,用于在组件中进行数据获取操作。它类似于 Vue 3 中 的 setup() 钩子。 Nuxt 封装提供了 4 个函数 useFetch、useLazyFetch、useAsyncData 和 useLazyAsyncData 来处理应 用程序中的数据获取。useFetch 是基于另外 3 个函数的封装。 useFetch() 钩子可以让你方便地获取远程数据,将数据存储在组件的状态中,并在组件中使用数据。

// TODO 接口请求
const imgSrc=ref('')
const param1 = ref('value1')
const res = await useFetch('https://dog.ceo/api/breeds/image/random',{
 query: { param1, param2: 'value2' },
 server: false //设置为false就可以在浏览器中看到
})
imgSrc.value = res.data.value?.message
console.log("接口请求处理中...", res.data.value?.message)