一篇热乎的Nuxt3.js秘籍
前言
这是一篇关于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
接下来你会看到下面的网页那么我们的第一个项目就创建成功了,完结撒花
Nuxt 框架的自动导入功能
我们打开项目后可以看到一个app.vue
这个是入口页面,这个页面中可以看到<NuxtRouteAnnouncer /> <NuxtWelcome />
这两个组件都是Nuxt
的内置组件,我们并没有用引入且可以直接使用,这就是Nuxt
的自动导入功能,除了可以自动导入内置组件外,还支持自动导入自定义组件,如下
components
下有子目录,会取上一级目录名加自身目录名,如下
- 如果子目录名字与组件本身名重复,重复的部分会被去掉,如下
Nuxt 应用的页面与路由
在Nuxt
中是基于文件系统产生的路由,不需要单独去定义路由,只需要在特定的文件中创建文件就行,Nuxt
会根据路径和名字自动生成路由,如下
在 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就会变为'关于'这两个字,如下
使用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>
当然我们也可以设置自己需要的布局,比如你想about.vue
这个页面不采用你写的默认布局方式,那我们可以在layouts
文件夹中新建一个布局页面,在你需要的页面更换布局即可,如下
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
中也是可以写接口服务的,这不就我们迈向全栈的利器吗?
但是呢这个接口发送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}`,
};
});
在 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
Nuxt
将fetch
封装了一下叫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 相当于$fetch
与useAsyncData
的结合体
<script setup>
const { data, pending, refresh, error } = await useFetch(
'http://localhost:3000/api/greet',
);
console.log(data);
</script>
这样的话,我们可以结合前面说的runtimeConfig
与 composables
,在项目中就可以对网络请求加以封装了
- 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