一、项目搭建
1. 脚手架安装nuxt3
npx nuxi@latest init <project-name>
2. 安装ui框架
npm install -D @element-plus/nuxt
// nuxt.config.ts
export default defineNuxtConfig({modules: ['@element-plus/nuxt'], //引入element-plus模块
})
3.安装pinia
npm install pinia @pinia/nuxt
如果安装失败,将以下内容添加到 package.json
中
"overrides": {"vue": "latest"
}
// nuxt.config.ts
export default defineNuxtConfig({modules: ['@pinia/nuxt',],
})
二、nuxt.config.ts的一些配置
export default defineNuxtConfig({compatibilityDate: "2024-04-03",devtools: { enabled: true },modules: ["@element-plus/nuxt", "@pinia/nuxt"], //导入模块css: ["element-plus/dist/index.css"], //引入全局样式app: {head: {title: "nuxt3学习", //全局设置网页标题,也可以在页面去设置局部标题meta: [{name: "description",content: "Nuxt 3",},],},},runtimeConfig:{ //运行时的配置,用于定义全局变量 用法下面的代码public:{ //public是服务端和客户端都能拿到值baseUrl:"localhost:3000"},abc:"123" //只能服务端拿到值}
});
//获取runtimeConfig里面的值
const config = useRuntimeConfig();
console.log(config.abc,"config.abc"); //服务端打印123,客户端undefined
console.log(config.public.baseUrl,"config"); //服务端和客户端都一样
三 、路由
nuxt3使用的是约定式路由,只需要在根目录的pages
页面中创建文件就行了,/
路径对应的是index.vue
文件,比如localhost:3000
就会访问pages/index.vue
文件,localhost:3000/login
就会访问pages/login.vue
,localhost:3000/users/test
就会访问pages/users/test.vue
这样就实现了嵌套路由.
-| pages/
---| index.vue
---| login.vue
---| users/
-----| test.vue
-----| index.vue
命名路由
使用方式和vue-router是一样的,通过localhost:3000/users/123
访问
-| pages/
---| users/
-----| [abc].vue
const route = useRoute();
let abc= ref(route.params.abc); //获取命名路由传递的参数
可选路由
localhost:3000/users/test
和localhost:3000test
访问的是同一个页面
-| pages/
---| [[user]]/
-----| test.vue
全局路由
一般用于404页面,只要路由没有匹配上就来这个页面
-| pages/
---| [...abc].vue
vue-router
里面的<router-view/>
组件替换成了<NuxtPage />
,当然也可以自定义路由,在页面中使用definePageMeta
,路由跳转也变成了navigateTo
,用法和router.push
是一样的
definePageMeta({path:"/testLogin"
})
navigateTo("/testLogin");
局部路由守卫
在根目录创建middleware
文件夹,随便创建一个文件
//test.ts
export default defineNuxtRouteMiddleware((to, from) => {console.log(to,"to");
});
在需要的页面使用
definePageMeta({middleware:["test"]
});
全局路由守卫
和局部路由守卫定义方式是一样的,只是命名方式不一样,abc.global.ts
,需要在文件名中加入global
,不需要在任何文件中使用就能全局路由拦截
四、composables文件夹
在这个文件夹里面的文件都会进行自动导出,但是只限于第一层,比如下面的test
文件中的myTest.ts
文件就不会自动导出,有两种导出方式,见下方代码
-| composables/
---| abc.ts
---test/
------myTest.ts
// abc.ts
export const add = (x, y) => {return x + y;
};
export default (x, y) => {return x + y;
};
console.log(add(1,2),"add"); //具名导出直接使用导出名
console.log(abc(1,2),"abc"); //默认导出使用文件名
五、useAsyncData
这个hook主要用于网络请求,如果直接使用$fetch('https://api.nuxtjs.dev/mountains')
,那么服务端会执行一次,客户端也会执行一次,这样会增加服务器压力,所以使用useAsyncData
会有一个缓存效果,当发现第一个参数也就是下面的mountains
相同的时候,就直接使用缓存的数据,不会再执行里面的代码,类似于计算属性,useAsyncData
必须返回一个promise
const { data, pending, error, refresh } = await useAsyncData('mountains',() => $fetch('https://api.nuxtjs.dev/mountains')
)
六、 网络请求封装
axios
搭配useAsyncData
来使用,在上面封装一层,也可以使用nuxt3提供的useFecth
,也是封装一层,让所有的接口都走封装的方法,具体使用方法
const { data, pending, error, refresh } = await useFetch('/api/auth/login', {onRequest({ request, options }) {// 这里是请求拦截options.headers = options.headers || {}options.headers.authorization = '...'},onResponse({ request, response, options }) {//这里是响应拦截,不管成功还是失败都走这里// Process the response datareturn response._data},onResponseError({ request, response, options }) {//这里是失败的响应拦截}
})
7. state
const a = ref(0);
a.value++;
console.log(a.value,"a.value"); //1
上面这串代码会打印1,虽然服务端和客户端都执行了一次,但是每次a都重新赋值了,那么该如何让其打印2呢,第一种方法就是定义在runtimeConfig
的public
里面,第二种方式就是使用state
const test = useState("abc",() =>{return 0;
});
test.value++;
console.log(test.value,"test.value") //2
这里的state是全局共享的,类似于pinia
,可以在任何页面使用useState("test").value
来获取值
8.打包发布
npm run build
,执行文件在.output/server/index.mjs