加载中...

Nuxt3 学习笔记 记录开发流程、bug解决、小坑优化 通俗易懂,持续更新 时光小灶

Nuxt3 学习笔记 记录开发流程、bug解决、小坑优化 通俗易懂,持续更新 时光小灶

Nuxt3官方文档:https://nuxt.com/
Nuxt3中文文档:https://nuxt.com.cn/
模板目录结构文档:https://nuxt.com/docs/guide/directory-structure/nuxt
作者:时光
个人博客:https://timebk.cn/
版权声明:原创文章,请勿抄袭,思维有限,敬请指正,转载需注明作者和原文

安装

npx nuxi init <project-name>
  • 1
  • 安装的时候很大几率会遇到 Failed to download template from registry: fetch failed 这个问题,中文直译过来就是 无法从注册表下载模板:获取失败 ,放心,这不是你和你的网络问题!

网上的解决方法

1. 挂机场 // 实际无效
2. 修改本地网络DNS为114.114.114.114 // 实际无效
3. 在系统hosts文件里添加 raw.githubusercontent.com [该域名ip] // 实际无效
  • 1
  • 2
  • 3

【重要】没错,上面的三种方法都基本无效!

最优的方法

访问以下链接:

初始模板里的 package.json

{
  "private": true,
  "scripts": {
    "build": "nuxt build", // 打包
    "dev": "nuxt dev", // 开发
    "generate": "nuxt generate", // 静态生成
    "preview": "nuxt preview", // 预览
    "postinstall": "nuxt prepare" // 脚本处理
},
  "devDependencies": {
    "nuxt": "^3.3.1"
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

路由 > pages目录

Nuxt 是属于约定式的,在路由这方面很有新意

  • 首先第一件事情就是删除 app.vue 里的 <NuxtWelcome />,这个是Nuxt官方的欢迎组件
  • 然后在 app.vue 里添加 <NuxtPage :page-key="$route.fullPath" />
  • 现在,我们只需要在根目录创建一个 pages 文件夹
  • 接着在 pages 文件夹里新增一个 .vue 文件(名称的话你自己取,我这里为了方便教程就命名为 about.vue ),然后这个文件就已经进入路由了,你可以通过 http://localhost:3000/about 访问了

New Image
New Image

  • 当然, pages 目录下的 index.vue 文件则是首页

嵌套路由

实际项目的需求咱们肯定不是只有 localhost:3000/about 这种一级路由,还会有 localhost:3000/about/1localhost:3000/about/1/1 这种嵌套路由

  • 在Nxut3中,咱们要实现这种嵌套路由,是需要新建 同级相同名称目录 的,以下我会继续以 /about 来作为讲解
  • 比如我们现在有一个 /about 页了,我们现在需要 /about/1 页面,那么我们就需要在同级文件夹新建一个 about 文件夹,再在这个文件夹里新建一个 1.vue

New Image
New Image

  • 我们现在来通过 useRouter().options.routes 看一下routes的结构

New Image

  • 这个结构是不是很熟悉?Nuxt3为我们自动生成了嵌套路由
  • 更多级的路由你只需要套娃式地操作即可咯,注意,如果你不设置同级相同名称的目录和.vue文件,那么不会形成嵌套关系

布局 > layouts目录

这是Nuxt提供的一个可定制的公共布局框架

  • 在项目根目录下创建一个 layouts 文件夹

New Image

  • 然后我们在 layouts 文件夹下新建一个 default.vue ,它将作为 <NuxtLayout /> 的默认布局

New Image
New Image

  • 注意,这里的 <slot /> 是作为插槽出口,你需要有一定的Vue插槽概念基础:查看Vue官方插槽讲解
  • 接着,在需要用到该布局的页面文件里添加 <NuxtLayout><NuxtLayout /> 即可

New Image

  • 这里的 <slot /> 是作为插槽出口,你甚至可以定义 name 来区分插槽
  • 你在 <NuxtLayout><NuxtLayout /> 里添加的元素将添加到布局文件里的 slot插槽出口

New Image

  • 当然,你可以通过v-if条件编译区分公共布局是前台还是后台
  • 如果我们需要为某个页面指定某个布局,我这里用 admin 来作为演示,在 layouts 文件夹下新建一个 admin.vue,然后在需要用到该布局的页面文件里添加 <NuxtLayout name="admin" ><NuxtLayout /> 即可

中间件 > middleware目录

实际开发中,我们也许会在跳转某个路有前做点什么操作,或者说是决定是否跳转点击的路由

  • 在项目根目录下创建 middleware 文件夹
  • 这个文件夹里面的文件是以 .js 或者 .ts(推荐)为格式的
  • 你也可以叫他 导航守卫前

全局中间件

  • 我们首先就需要定义一个全局的中间件,它的命名应该是 default.global.ts ```
export default defineNuxtRouteMiddleware((to: any, from: any) => {
  
});
  • 1
  • 2
  • 3
  • tofrom 是什么就不用多说了吧,就是获取上一个路由和下一个路由的路由信息,这个在Vue原生模板中我们必用的一个东西,不过注意这个中间件属于 导航前
  • 然后你就可以根据业务需求编写代码了,它的一些语法请看官网学习,这里只是记录入门

扩展

在中间件里获取document、windows等

有的时候我们可能需要在这里获取Html元素,这时候我们不能直接获取到元素,比如document、windows等等因为是在服务端没有挂载前是不存在的
New Image
New Image

  • 那么怎么解决呢
  • 我们可以通过异步加载的方式获取

New Image
New Image

  • 不过我是不推荐在中间件里操作document的,因为有的时候会出现莫名其妙的问题,比如我之前在这里面通过接口获取网站配置并保存到 Pinia 里,出现了服务器部署后访问项目强制刷新时无法获取到 Pinia 里的数据,所有还是推荐直接在 app.vue 里进行类似操作

SEO优化和动态组合式Title

这个官网上有提,但是坑特别多,文档根本不完善,我这里记录一下我的方案

  • 众所周知,网站是需要推广的,推广就需要较好的SEO,才能在搜索引擎上有较好的排名(当然你愿意花钱让别人帮你做词和提权重也不是不可以哈哈哈)
  • 除了开发时注意标签语义化和尽量保证清晰的HTML结构,我们还需要在动态seo上面做努力~
  • 下面以页面 tiitle 作为例子哈!
  • nuxt.config.ts 文件里,我们可以通过配置 app.head.title 来设置全局的页面title

New Image

  • 但是实际项目中我们肯定是需要每个页面都要有一个自己的title,而且可以组合base title的
  • 我们需要这样做:

例子:近乎完美的SEO Title

  • 先在 app.vue 里添加 useHead() 配置

New Image

useHead({
  titleTemplate: (productCategory) => {
    const baseTitle = "时光小灶";
    return `${productCategory ? productCategory + " - " : ""}${baseTitle}`;
  },
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 然后,在我们的每个页面添加一个 <Title></Title> 组件,标签里面的字符将作为当前页面的动态title

New Image

  • 最终效果:

New Image

  • 之后你部署到服务器和绑定域名后,通过第三方的seo查询均可以正常获取每个页面的title

Vue3 UI库 Element Plus

安装

npm i @element-plus/nuxt -D
  • 1
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@element-plus/nuxt"],
  elementPlus: {
    /** Options */
  },
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 安装好后就不需要手动import引入了

使用Icon 图标

  • elementPlus 中添加 icon: "ElIcon"
export default defineNuxtConfig({
  modules: ["@element-plus/nuxt"],
  elementPlus: {
    /** Options *
    icon: "ElIcon",
  },
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

手动导入

  • 现在,你可以通过 import { User, Lock } from "@element-plus/icons-vue"; 来使用所需要的图标
  • 但是这种很麻烦,每一个图标都需要手动导入一下

自动导入

  • plugins 文件夹里的 global.ts 文件里添加如下代码
import * as ElementPlusIconsVue from "@element-plus/icons-vue";

export default defineNuxtPlugin(async (NuxtApp) => {
  // 其他code
  // 全局组件引入
  for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    NuxtApp.vueApp.component(key, component);
  }
  // 其他code
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Pinia 及 持久化

安装

npm i pinia @pinia/nuxt
  • 1

使用

  • 项目名根目录 创建 stores 文件夹
  • stores 文件夹里创建一个 .ts 文件,文件名自己取,之后使用的时候正确路径导入即可,下面以 adminInfo.ts 作为示例
// adminInfo.ts
import { defineStore } from "pinia";

export const adminConfig = defineStore("adminConfig", {
  state: () => {
    return {
      adminConfig: {},
    };
  },
  actions: {
   adminConfigSet(data = {}) {
      this.adminConfig = data;
    },
  },
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 然后需要使用的页面导入即可
import { adminConfig } from "~/stores/adminConfig";
const store = reactive<any>(adminConfig().adminConfig);
  • 1
  • 2
  • 更多的关于Pinia知识点请到官网学习:Pinia官网

持久化 pinia-plugin-persistedstate

安装

  • 为了实现持久化,我们需要使用到一个依赖 @pinia-plugin-persistedstate/nuxt
npm i -D @pinia-plugin-persistedstate/nuxt
  • 1
  • 然后在 nuxt.config.ts 里添加配置
export default defineNuxtConfig({
  // other code
  modules: ["@pinia/nuxt", "@pinia-plugin-persistedstate/nuxt"],
  // other code
});
  • 1
  • 2
  • 3
  • 4
  • 5

用法

  • 创建 Store 时,将 persist 选项设置为 true
// adminInfo.ts
import { defineStore } from "pinia";

export const adminConfig = defineStore("adminConfig", {
  state: () => {
    return {
      adminConfig: {},
    };
  },
  actions: {
   adminConfigSet(data = {}) {
      this.adminConfig = data;
    },
  },
  persist: true,// 设置为true
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

注意

  • 默认情况下,Store 将被保存在 cookie 中(在底层使用 Nuxt 的 useCookie)

选择 storage

  • 但可以通过使用自动导入的 persistedState 变量下的可用 storage 来配置你想要使用的 storage
import { defineStore } from "pinia";

export const adminConfig = defineStore("adminConfig", {
  state: () => {
    return {
      adminConfig: {},
    };
  },
  actions: {
   adminConfigSet(data = {}) {
      this.adminConfig = data;
    },
  },
  persist: {
  // 下面的二选一
    storage: persistedState.localStorage,// localStorage
    storage: persistedState.sessionStorage,// sessionStorage
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

更多待补充…