likes
comments
collection
share

一篇热乎的Nuxt3.js秘籍

作者站长头像
站长
· 阅读数 21

前言

这是一篇关于Nuxt3的一篇文章,希望可以帮助你快速掌握Nuxt,落地自己的项目,其他的就不说了,都是废话,文中如有错误,望各位大佬批评指正!

SSR

Nuxt的之前肯定要了解一下服务端渲染的(SSR),服务器端渲染(Server-Side Rendering)是指由服务端生成HTML并发送浏览器,概念枯燥无趣,不需要在意,无所diao谓,就说两点吧

  • SSR对搜索引擎友好,可以提高页面的首页加载速度,另外一个就是更有利于SEO
  • 比较吃服务器性能

创建 Nuxt 项目

创建 Nuxt 项目之前需要安装Node,这就不赘述了,官方建议Node版本在v18.0.0及以上

// 初始化项目
npx nuxi@latest init <project-name>

// 进入自己的项目
cd project-name

// 运行项目
pnpm run dev

接下来你会看到下面的网页那么我们的第一个项目就创建成功了,完结撒花

一篇热乎的Nuxt3.js秘籍

Nuxt 框架的自动导入功能

我们打开项目后可以看到一个app.vue这个是入口页面,这个页面中可以看到<NuxtRouteAnnouncer /> <NuxtWelcome />这两个组件都是Nuxt 的内置组件,我们并没有用引入且可以直接使用,这就是Nuxt的自动导入功能,除了可以自动导入内置组件外,还支持自动导入自定义组件,如下

一篇热乎的Nuxt3.js秘籍

  • components下有子目录,会取上一级目录名加自身目录名,如下

一篇热乎的Nuxt3.js秘籍

  • 如果子目录名字与组件本身名重复,重复的部分会被去掉,如下

一篇热乎的Nuxt3.js秘籍

Nuxt 应用的页面与路由

Nuxt中是基于文件系统产生的路由,不需要单独去定义路由,只需要在特定的文件中创建文件就行,Nuxt会根据路径和名字自动生成路由,如下

一篇热乎的Nuxt3.js秘籍

app.vue中写入<NuxtPagge /> 这个内置组件,可以将它理解为路由的视图,路由出口,如果你还想定义其他的路由只需要pages在定义vue文件即可,路由就是你的文件名

动态路由

开发中难免会使用到动态路由,比如新闻页,产品页,点进去是详情页,这个时候我们可以考虑用到动态路由,对文件结构进行更改

-| pages/
---| posts
-----| index.vue
-----| [id].vue

这样的我们就可以访问/posts/[id],这里的id就是动态的,可以在页面中进行获取

<template>
  <p>{{ $route.params.id }}</p>
</template>

or

<script setup lang="ts">
const { params :{id} }= useRoute()
</script>

路由导航

如果你需要在页面之间导航,你应该使用 <NuxtLink> 组件,这是一个内置组件,可以直接使用

<template>
  <NuxtLink to="/">Home page</NuxtLink>
</template>

中间件(路由守卫)

Nuxt中存在一个中间件的概念,类似于vue-router的路由守卫,新建一个midleware文件夹,文件夹中放的就还是我们自己定义的中间件,中间件分为两种,一种是全局中间件,一种是组件中间件

  • 全局中间件 需要在名字上加.global 例如:log.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
    console.log(`全局中间件:从${from.path}${to.path}`);
  })

  • 组件中间件 在组件中引入使用,非全局,在midleware文件夹下新建auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  console.log(`auth 中间件`);
});

// about.vue
<script setup lang="ts">
definePageMeta({
  middleware: ['auth'],
});
</script>

在 Nuxt 组件里自定义网页标题

Nuxt中我们可以自行修改title标签的值,可以采用两种方式进行修改

使用meta组件

Nuxt中自带一些关于meta的组件,比如head body title等等,如下

// about.vue
<template>
  <div>
    <Head>
      <Title>关于</Title>
    </Head>
    <h1>关于</h1>
  </div>
</template>

这样设置的话,关于这个页面的title就会变为'关于'这两个字,如下

一篇热乎的Nuxt3.js秘籍

使用useHead

<script setup lang="ts">
useHead({
  title: "关于",
});
</script>

这样设置也可以实现上面的效果,但是这样还是很麻烦,在项目中如果标题有重复的部分,这样写下来也不方便,于是Nuxt提供了相应的配置,配置动态模板以实现自定义单个页面的页面标题。我们可以在app.vue中进行如下配置

Nuxt 页面的布局 Layout

我们在开发过程中页面肯定需要一些基础的组件,比如标题,导航栏,侧边栏等等,Nuxt提供了布局相关的配置,帮助我们提高开发效率,默认情况下将使用layouts/default.vue 文件,在app.vue 中使用NuxtLayout进行包裹即可

// layouts/default.vue
<template>
  <div class="app">
    <header>
      <div>
        <span>我是公共头部</span>
      </div>
    </header>
    <main>
      <slot></slot>
    </main>
  </div>
</template>
<style>
header {
  border-bottom: 2px solid #ccc;
  padding: 20px 0;
}
</style>

// app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

一篇热乎的Nuxt3.js秘籍

当然我们也可以设置自己需要的布局,比如你想about.vue这个页面不采用你写的默认布局方式,那我们可以在layouts文件夹中新建一个布局页面,在你需要的页面更换布局即可,如下

一篇热乎的Nuxt3.js秘籍

Nuxt 框架的模块 Module

Nuxt提供了一套模块系统,可以扩展Nuxt的功能,我们可以使用现成的模块也可以自己开发模块,Nuxt本身提供很多模块,可以与官网看下,接下来我们用@nuxt/image-edge模块举个栗子

pnpm install @nuxt/image-edge

nuxt.config.ts中进行配置

export default defineNuxtConfig({
  modules: ['@nuxt/image-edge'],
  image: {
    // 该选项将用于检测远程图像是否应被优化
    domains: ['t7.baidu.com'],
  },
});

在页面中使用nuxt-img即可

<template>
  <div>
    <nuxt-img
      quality="30"
      src="https://t7.baidu.com/it/u=1500571650,3211010172&fm=193&f=GIF"
      alt=""
    />
  </div>
</template>

使用这个模块可以将外部图片进行优化,减少图片体积,有兴趣的可以刺激测试一下,我这里就不展示了,截图频繁,很烦

Nuxt 应用里定义服务端应用接口

nuxt中你自己可以去写接口,这些接口放在server文件夹下

-| server/
---| api
-----| greet.ts

// greet.ts
export default defineEventHandler(() => {
  return {
    message: '你好',
  };
});

这样我们就定义了一个接口,我们可以访问它看下,不出意外的话他就是通的,所有nuxt中也是可以写接口服务的,这不就我们迈向全栈的利器吗?

一篇热乎的Nuxt3.js秘籍

但是呢这个接口发送post接口它也是通的,如果我们想只要它发送get请求 我们只需要遵循nuxt的规范就行,只需要把文件名上加上get即可,如下

-| server/
---| api
-----| greet.get.ts

那如果想传参该怎么弄呢? 也很简单,我们只需要更改一下目录结构

-| server/
---| api
----| greet
-----| [name].get.ts

name 就是路由地址的一个参数

// [name].get.ts
export default defineEventHandler(({ context }) => {
  const {
    params: { name },
  } = context;
  return {
    message: `你好${name}`,
  };
});


一篇热乎的Nuxt3.js秘籍

在 Nuxt 项目里自定义组合(Composables)

我们可以定义一些方法在项目中,这些方法不需要导入,就可以直接使用,我们只需要新建目录composables,但是文件名必须是以use开头

-| composables/
---| use-api-fetch.ts

// use-api-fetch.ts
export const useApiFetch = () => {
  console.log('useApiFetch');
};

// about.vue
useApiFetch()  // 直接使用就行,不需要引入

Nuxt 项目中的运行时配置(runtimeConfig)

Nuxt提供了一个运行时配置的API,在你的应用程序和服务器路由中暴露配置,并能在运行时通过设置环境变量进行更新。

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiBaseUrl: 'https://baidu.com',
    },
  },
});

比如我们就可以在我们上面定义的 use-api-fetch.ts文件中使用useRuntimeConfig访问到这个变量

// use-api-fetch.ts
export const useApiFetch = () => {
  const {
    public: { apiBaseUrl },
  } = useRuntimeConfig();
  console.log('apiBaseUrl:', apiBaseUrl);
};

apiBaseUrl这个值可以被环境变量所覆盖掉,接下来我们在项目的根目录定义一个.env文件,里面的变量必须以NUXT开头

Nuxt 应用里使用发送网络请求

Nuxt提供了多种发送请求的方式

  • $fetch
  • useFetch
  • useAsyncData

$fetch

Nuxtfetch封装了一下叫ofetch,大家平时使用vue开发的时候也是可以使用的

<script setup lang="ts">
// During SSR data is fetched twice, once on the server and once on the client.
const dataTwice = await $fetch('/api/item')
</script>

也可以在发放中使用

<script setup lang="ts">
function contactForm() {
  $fetch('/api/contact', {
    method: 'POST',
    body: { hello: 'world '}
  })
}
</script>

<template>
  <button @click="contactForm">Contact</button>
</template>

useAsyncData

nuxt中可以使用useAsyncData去请求异步数据,第一个参数是一个唯一的key,这个可以确保在请求的时候去除重复的数据,第二个参数是一个函数,看个例子

<script setup>
const { data, pending, refresh, error } = await useAsyncData('item', () =>
  $fetch('http://localhost:3000/api/greet'),
);
console.log(data);
</script>

useAsyncData会阻止导航,就是说当数据没有拿到的时候页面是不会跳转的

如果你想不想阻止导航的话,可以给useAsyncData配置一个lazy属性,这个时候数据就算为null,页面也会跳转,所以页面中记得处理数据为空时的显示效果,结合pending

<script setup>
const { data, pending, refresh, error } = await useAsyncData(
  'item',
  () => $fetch('http://localhost:3000/api/greet'),
  { lazy: true },
);
console.log(data);
</script>
  • data 就是我们的数据
  • penging代表请求时的状态,有四种状态("idle""pending""success""error");
  • refresh可用于刷新处理函数,分页的时候,我们点击上一页就可以用到refresh进行再一次的请求
  • error 如果数据获取失败,则返回一个错误对象

useFetch

useFetch 相当于$fetchuseAsyncData的结合体

<script setup>
const { data, pending, refresh, error } = await useFetch(
  'http://localhost:3000/api/greet',
);
console.log(data);
</script>

这样的话,我们可以结合前面说的runtimeConfigcomposables ,在项目中就可以对网络请求加以封装了

  • composables/ use-api-fetch.ts
// composables/ use-api-fetch.ts
export const useApiFetch = (api: string | (() => string)) => {
  const {
    public: { apiBaseUrl },
  } = useRuntimeConfig();
  return useFetch(api, { baseURL: apiBaseUrl });
};

  • .env
NUXT_PUBLIC_API_BASE_URL = "http://localhost:3000/api"
  • nuxt.config.ts
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiBaseUrl: '',
    },
  },
});
  • 页面中
// composables/ use-api-fetch.ts
export const useApiFetch = (api: string | (() => string)) => {
  const {
    public: { apiBaseUrl },
  } = useRuntimeConfig();
  return useFetch(api, { baseURL: apiBaseUrl });
};

大家可以在use-api-fetch.ts文件中尽情发挥自己的想象,结合自己的业务需求进行封装!

总结

Nuxt基本使用就算说完了,大家感兴趣多去官网逛逛,里面可以解决你的很多需求,Nuxt个人觉得是前端进入全栈的一块敲门砖吧,希望各位前端伙伴认真学习,拜拜, 最后还是下方这句话,望共勉!

夫学须静也,才须学也,非学无以广才,非志无以成学。淫慢则不能励精,险躁则不能治性。年与时驰,意与日去,遂成枯落

转载自:https://juejin.cn/post/7389912354748252171
评论
请登录