前言
Nuxt 官网表示,Nuxt 是一个开源框架,使 Web 开发直观而强大。使用 Nuxt 可以自信地创建高性能和生产级的全栈 Web 应用程序和网站,并且得到众多知名公司前端团队的信任。
Nuxt 是前端工程师进阶全栈工程师的必由之路,值得一提的是,Nuxt 框架是基于 Vue 生态的上层封装并且帮我们内置了很多功能,只要熟悉 Vue 技术栈和 Node 基础,就可以快速上手 Nuxt。
我的另一篇文章拥抱全栈框架 Nuxt | 配置篇详细讲解了如何创建 Nuxt 项目并配置项目,而这一篇拥抱全栈框架系列的基础篇,结合着文章和 Nuxt 官网,我相信掌握 Nuxt 基础不是一件难事。
Nuxt 基础知识
Nuxt 内置组件
Nuxt3 框架也提供一些内置的组件,常用的如下:
NuxtLayout:是 Nuxt 自带的页面布局组件。
NuxtWelcome:欢迎页面组件,该组件是 @nuxt/ui 的一部分。
ClientOnly:该组件中的默认插槽的内容只在客户端渲染,而fallback插槽的内容只在服务器端渲染。
<template>
<div class="home">
<div>我是Home Page</div>
<ClientOnly>
<div>我只会在 client 渲染</div>
<template #fallback>
<h2>服务器端渲染的 loading 页面</h2>
</template>
</ClientOnly>
</div>
</template>
NuxtLink:是 Nuxt 自带的页面导航组件,是 Vue Router<RouterLink>组件 和 HTML<a>标签的封装。
SEO组件:<Title>, <Base>, <NoScript>, <Style>, <Meta>, <Link>, <Body>, <Html> and <Head>。
NuxtPage:是 Nuxt 自带的页面占位组件,需要显示位于目录中的顶级或嵌套页面 pages/ 目录中,是对 router-view 的封装。
<template>
<div>
<h1>App</h1>
<!--是 对 router-view 封装 -->
<NuxtPage></NuxtPage>
</div>
</template>
全局样式
编写全局样式、全局变量步骤
- 在 assets 文件中编写全局样式,比如:globel.scss;
// 全局样式
$color: blue;
.global-style {
color: $color;
}
- 在 assets 文件中编写全局样式变量,比如: variables.scss;
// 定义全局的SCSS变量
$fsColor: purple;
$fs20: 20px;
// 混合
@mixin border() {
border: 1px solid red;
}
- 在 nuxt.config 中的 css 选项、vite 选项中进行配置,使定义的全局样式和全局变量生效
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
// 定义全局样式
css: [
"@/assets/styles/global.scss"
],
// 定义全局变量
vite: {
css: {
preprocessorOptions: {
scss: {
// 自动的给 scss 模块首行添加额外的数据: @use "@/assets/styles/variables.scss" as *;
additionalData: '@use "@/assets/styles/variables.scss" as *;',
},
},
},
},
});
- 接着在命令行终端执行
npm i –D sass即可,然后就可以在任意组件中或 scss 文件中直接使用全局变量
资源的导入
public目录
用作静态资源的公共服务器,可以在应用程序上通过 URL 直接访问
例如,引用 public/img/ 目录中的图像文件,在静态 URL 中可用 /img/nuxt.png 表示
<template>
<div>
<!-- public 资源的访问 -->
<img src="/img/nuxt.png" alt="" />
</div>
</template>
静态的 URL 也支持在背景中使用,如 background-image: url(/logo.png)
assets目录
assets 经常用于存放如样式表、字体或 SVG 等资源
可以直接使用 ~/assets/ 路径引用位于 assets 目录中的资源文件
<template>
<div>
<!-- assets 资源的访问 -->
<img src="@/assets/images/avatar.png" alt="" />
<img src="~/assets/images/avatar.png" alt="" />
</div>
</template>
其实 ~/assets/ 路径也支持在背景中使用,如background-image: url(@/assets/images/avatar.png)
新建页面
Nuxt 项目中的页面是在 pages 目录下创建的
在 pages 目录创建的页面,Nuxt 会根据该页面的目录结构和其文件名来自动生成对应的路由
页面路由也称为文件系统路由器(file system router),路由是 Nuxt 的核心功能之一
新建页面步骤
- 创建页面文件,比如:
pages/index.vue - 将
<NuxtPage />内置组件添加到app.vue - 页面如果使用
scss那么需要安装:npm i sass -D
命令快速创建页面
npx nuxi add page home用来创建 home 页面npx nuxi add page detail/[id]用来创建 detail 页面npx nuxi add page user-[role]/[id]用来创建 user 页面
组件导航(NuxtLink)
<NuxtLink> 是 Nuxt 内置的组件,用来实现页面导航,本质上是对 RouterLink 的扩展,底层用的是一个 <a> 标签,因此使用 a + href 属性也支持路由导航。与 <NuxtLink> 不同的是,用 a 标签导航会有触发浏览器默认的刷新事件,而 <NuxtLink> 不会, <NuxtLink> 还扩展了其它的属性和功能,因此在 Nuxt 中我们可以使用 <NuxtLink> 进行组件之间的导航。
<NuxtLink> 组件的部分属性:
to: 支持路由路径、路由对象、 URL
<template>
<NuxtLink to="/about">
About page
</NuxtLink>
<!-- <a href="/about">...</a> (+Vue Router & prefetching) -->
<!-- 以路由对象的形式传入 -->
<NuxtLink
:to="{
path: '/category',
query: {
id: 100
}
}"
>
<button>category</button>
</NuxtLink>
</template>
href: to 的别名target: 和 a 标签的 target 一样,指定何种方式显示新页面
<template>
<NuxtLink href="https://www.nuxt.com" target="_blank">
<button>nuxt.com</button>
</NuxtLink>
</template>
replace: 默认为 false,是否替换当前路由
<template>
<NuxtLink href="/find" replace>
<button>find replace</button>
</NuxtLink>
</template>
activeClass: 激活链接的类名
<template>
<NuxtLink to="/home" active-class="active-home">
<button>home</button>
</NuxtLink>
</template>
编程式导航
navigateTo
Nuxt3 除了可以通过 <NuxtLink> 内置组件来实现导航,同时也支持编程导航:navigateTo,通过编程式导航,在应用程序中就可以轻松实现动态导航了,但是编程式导航不利于 SEO。navigateTo 函数在服务器端和客户端都可用,可以在插件、中间件中使用,也可以直接调用执行页面导航。
其中 navigateTo( to , options) 函数包含两个参数:
第一个参数 to 可以是纯字符串或外部 URL 或路由对象;
第二个参数 options 为导航配置:
- replace:默认为 false,为 true 时会替换当前路由页面
- external:默认为 false,不允许导航到外部连接,true 则允许
在 Vue 组件中直接使用
<script setup lang="ts">
// passing 'to' as a string
await navigateTo('/search')
// ... or as a route object
await navigateTo({ path: '/search' })
// ... or as a route object with query parameters
await navigateTo({
path: '/search',
query: {
page: 1,
sort: 'asc'
}
})
</script>
在中间件中使用
export default defineNuxtRouteMiddleware((to, from) => {
if (to.path !== '/search') {
// setting the redirect code to '301 Moved Permanently'
return navigateTo('/search', { redirectCode: 301 })
}
})
useRouter
Nuxt3 中的编程导航除了可以通过 navigateTo 来实现导航,同时也支持 useRouter (或 Options API 的 this.$router)。
- back:页面返回,同 router.go(-1)
- forward:页面前进,同 router.go(1)
- go:页面返回或前进,如 router.go(-1) or router.go(1)
- push:以编程方式导航到新页面,建议改用 navigateTo,支持性更好
- replace:以编程方式导航到新页面,但会替换当前路由,建议改用 navigateTo,支持性更好
- beforeEach:路由守卫钩子,每次导航前执行(用于全局监听)
- afterEach:路由守卫钩子,每次导航后执行(用于全局监听)
<template>
<div>
<!-- 通过编程的方式进行导航 -->
<button @click="goToHome">Go Home</button>
</div>
<!-- 是对router-view的封装 -->
<NuxtPage></NuxtPage>
</template>
<script setup>
// useRouter
let router = useRouter();
function goToHome() {
router.push("/home")
}
function goBack() {
router.go(-1);
}
// 路由的守卫
router.beforeEach((to, form) => {
console.log(to)
console.log(form)
})
</script>
动态路由
Nuxt3 和 Vue 一样,也是支持动态路由的,在 Nuxt3 中,动态路由是根据目录结构和文件的名称自动生成
动态路由语法:
- 页面组件目录或页面组件文件都 支持 [ ] 方括号语法
- 方括号里编写动态路由的参数
例如,动态路由支持如下写法:
pages/detail/[id].vue->/detail/:idpages/detail/user-[id].vue->/detail/user-:idpages/detail/[role]/[id].vue->/detail/:role/:idpages/detail-[role]/[id].vue->/detail-:role/:id
路由参数( useRoute )
动态路由参数
通过 [ ] 方括号语法定义动态路由,比如: /detail/[id].vue。
页面跳转时,在 URL 路径中传递动态路由参数,比如: /detail/100。
目标页面通过 route.params 获取动态路由参数。
示例:导航页面
<template>
<div>
<NuxtLink to="/detail/100">
<button>detail</button>
</NuxtLink>
<!-- router-view -->
<NuxtPage></NuxtPage>
</div>
</template>
示例:获取数据页面
<template>
<div>id={{ id }}</div>
</template>
<script lang="ts" setup>
// 拿到动态路由的参数
const route = useRoute()
const { id } = route.params
</script>
<style scoped></style>
查询字符串参数
页面跳转时,通过查询字符串方式传递参数,比如: /detail/100?name=zhangsan。
目标页面通过 route.query 获取查询字符串参数。
示例:导航页面
<template>
<div>
<NuxtLink to="/detail/100?name=zhangsan">
<button>detail</button>
</NuxtLink>
<!-- router-view -->
<NuxtPage></NuxtPage>
</div>
</template>
示例:获取数据页面
<template>
<div>id={{ id }} name={{ name }}</div>
</template>
<script lang="ts" setup>
// 获取动态路由的参数
const route = useRoute()
const { id } = route.params
const { name } = route.query
</script>
<style scoped></style>
路由匹配规则
路由匹配需注意的事项,预定义路由优先于动态路由,动态路由优先于捕获所有路由
预定义路由:pages/detail/create.vue
- 将匹配
/detail/create
动态路由:pages/detail/[id].vue
- 将匹配
/detail/1、/detail/abc等 - 但不匹配
/detail/create、/detail/1/1、/detail/等
捕获所有路由:pages/detail/[...slug].vue
- 将匹配
/detail/1/2,/detail/a/b/c等 - 但不匹配
/detail等
总结
Nuxt 框架是开箱即用的,并且学习成本也非常低,我们需要做的事情 Nuxt 都帮我们做好了,因此我们只要专注于业务的开发,而无需关心那些繁琐的配置。
对于一些内置的 API,我们不需要导入就可以直接使用;对于注册路由,我们直接使用 Nuxt 给我们提供的动态路由就可以直接导航到相应的页面,并直接获取路由参数;对于代码规范,Nuxt 也帮我们内置好了,布局相关的组件,我们直接只用 layout,有关中间件相关的,我们直接在 middleware 文件夹下定义。
Nuxt 相关的知识点不止这些,我们打开 Nuxt 官网大致浏览一下就会发现,内容非常丰富,知识点非常多,不过不用焦虑,由浅入深,分章节去学习是最好的方式。在下一篇文章《拥抱全栈框架 Nuxt | 进阶篇》中,我们会学习到 Nuxt 的页面渲染、插件开发、如何书写中间件、如何发送网络请求获取数据、如何写 API 接口、如何引入状态管理库 Pinia,以及如何引入第三方组件库等内容。