代码仓库
nuxt为我们提供了一些内置组件,可以直接使用不用导入,其中常用的如下
SEO组件可以更加方便的让我们再页面中添加利于seo的元素
欢迎页面组件,该组件是nuxt/ui的一部分
该组件时Nxut自带的页面的占位组件,是对router-view的封装,另外nuxt采用的是约定式路由,即不需要我们手动配置路由,nuxt会根据我们在pages文件夹中的文件以及app文件夹(开发中),具体的我们会在下边介绍。
该组件相当于vue-router中的router-link组件,用于页面跳转
组件属性
该组件的默认插槽的内容只会再客户端渲染,而fallback插槽的内容只在服务器端渲染
在服务端渲染期间,fallback内容会被渲染,一般会显示加载信息
home
home
该内容只会再服务器端渲染
该内容会再客户端渲染
(/pages/home/index.vue)
安装sass
yarn add sass -D
新建assets文件夹,并在该文件夹中新建css文件夹,新建global.scss文件用于写一些全局样式,新建value.scss用于保存全局变量
在nuxt.config.ts中配置
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
//全局引入样式
css: ["@/assets/css/global.scss"],
vite: {
css: {
preprocessorOptions: {
scss: {
// 每个文件中都会加上这句话
additionalData: "@use '@/assets/css/value.scss' as *;",
},
},
},
},
});
之后我们在/pages/index.vue中使用,就可以看到效果了
nuxt中提供两个目录用于存放静态资源,比如:stylesheets、fonts或img
例如:
<img
class="imgSty"
src="/01.jpg"
alt=""
/>
例如:
<img
src="@/assets/img/01.jpg"
class="imgSty"
alt=""
/>
/pages/index.vue
nuxt为我们提供了命令的方式去创建页面
# 创建home页面
npx nuxi add page home
home
nuxt3除了可以通过NuxtLink内置组件进行导航,也支持编程导航:navigateTo、useRouter
不过使用编程导航不利于SEO
navigateTo(url,options?);
// 无参
navigateTo("/about", {
replace: false,
external: false,
});
// 有参(可以传递query参数或者params参数)
navigateTo({
path: "/home",
query: {
type: "phone",
},
});
/pages/index.vue
const route = useRoute();
console.log(route.query);
//console.log(route.params);
/pages/home/index.vue
const router=useRouter();
// 页面返回,类似于router.go(-1);
router.back();
// 页面前进,类似于router.go(1)
router.forward();
// 页面前进或者返回(接收一个数字)
router.go(1);
// 以push方式导航到新页面
router.push({path:"/home"});//建议使用navigateTo代替
// 以replace方式导航到新页面
router.replace({path:"/home"});//建议使用navigateTo代替
// 路由全局守卫,每次导航前执行,用于全局监听,接收一个回调函数
router.beforeEach();
// 路由守卫,每次导航后执行,用于全局监听,接收一个回调函数
router.afterEach();
获取参数和navigateTo获取参数类似
我们可以使用[]方括号的形式来编写动态路由,方括号里边存放是动态路由的参数
pages/detail/[id].vue => /detail/:id
pages/detail/user-[id].vue => /detail/user-:id
pages/detail/[role]/[id].vue => /detail/:role/:id
通过route.params获取传递的参数
const route = useRoute();
const id = route.params.id;
nuxt为我们提供了404页面,但是并不适用于页面展示,我们可以自己定义404页面,通过方括号内添加三个点即表示捕获所有不匹配路由
例如:[…not].vue(not是一个名字,这个可以自定义)
pages目录中新建[…not].vue
再文件夹中创建一个与一级路由同名的文件夹就可以使用嵌套二级路由
- pages
---| parent/
----| index.vue
---| parent.vue
访问路径/parent/parent
我们的网站中经常会遇到每个页面中都包含一样的页头以及页脚
我们就可以使用layout来进行布局
再跟目录新建layouts文件夹
页面布局可以使用两种布局方式一种是默认布局,一种是自定义布局
在layouts目录下default.vue
然后再app.vue中通过NuxtLayout包裹
页头
页脚
在layouts中新建my-layout.vue,然后通过name属性指定布局类型(命名格式不能使用大驼峰)
我是自定义页头
我们也可以使用definePageMeta来指定当前页面布局模板,
使用时NuxtLayout不能指定布局方式否则不生效
definePageMeta({
layout: "my-layout",
});
/pages/about/index.vue
我们在之前项目中,我们一般使用axios去请求数据,但是在nuxt中,官方更加推荐我们使用useFetch而不是axios
import type { AsyncData, UseFetchOptions } from "nuxt/dist/app/composables";
const BASE_URL = "";
type Methods = "GET" | "POST";
class MyRequest {
request<T = any>(
url: string,
method: Methods,
data?: any,
options?: UseFetchOptions<T>
): Promise<AsyncData<T, Error>> {
return new Promise((resolve, reject) => {
const newOptions: UseFetchOptions<T> = {
baseURL: BASE_URL,
method: method,
...options,
};
if (method === "GET") {
newOptions.query = data;
}
if (method === "POST") {
newOptions.body = data;
}
useFetch<T>(url, newOptions as any)
.then((res) => {
resolve(res as AsyncData<T, Error>);
})
.catch((error) => {
reject(error);
});
});
}
get<T = any>(url: string, params?: any, options?: UseFetchOptions<T>) {
return this.request<T>(url, "GET", params, options);
}
post<T = any>(url: string, data?: any, options?: UseFetchOptions<T>) {
return this.request<T>(url, "POST", data, options);
}
}
export default new HYRequest();
使用pinia去实现全局状态管理
具体使用pinia的方式我会在下一个博客中详细说明
yarn add pinia @pinia/nuxt
在nuxt.config.ts中添加配置
modules: ["@pinia/nuxt"]
安装
yarn add element-plus
自动导入
yarn add unplugin-element-plus -D
babel 转义
yarn add unplugin-element-plus -D
// https://nuxt.com/docs/api/configuration/nuxt-config
import ElementPlus from "unplugin-element-plus/vite";
export default defineNuxtConfig({
devtools: { enabled: true },
css: [
"normalize.css",
"@/assets/css/global.scss",
"@/assets/cus-font/iconfont.css",
],
modules: ["@pinia/nuxt"],
// 配置自动导入样式
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: "@use '@/assets/css/variables.scss' as *;",
},
},
},
plugins: [ElementPlus({})],
},
app: {
// 可以给所有的页面的head添加一下SEO的信息
head: {
title: "",
meta: [
{
name: "description",
content:
"",
},
{
name: "keywords",
content: "",
},
{ name: "viewport", content: "width=device-width, initial-scale=1" },
],
link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }],
noscript: [{ children: "Javascript is required" }],
},
},
build: {
// 该文件需要进行Babel转义
transpile: ["element-plus/es"],
},
});