超详细的 nuxt3 使用分享
前言
在接下来的一周中 nuxt3 将迎来 rc 版本。作为喜欢尝鲜的用户,其实早早的就开始使用 nuxt3 了。以下是我在开发过程中的 nuxt3 的使用分享,希望对大家有所帮助。当然也可看线上文档 👉 MShared
介绍
Nuxt3
开源的高性能混合型 Vue 框架。
Featues
- 开发更快
- 打包更小
- 支持
vite - 支持
vue3 - 支持自动引入
- 支持文件路由
- 支持布局系统
- 支持多种渲染模式
- 支持
typescript - 支持
composition-api
安装
基础
- 创建
package.json,并补充以下信息 👇
{
"scripts": {
"dev": "nuxi dev",
"build": "nuxi build",
"start": "nuxi build && node .output/server/index.mjs"
},
"devDependencies": {
"nuxt3": "latest"
}
}
- 在根目录下创建
app.vue
<!-- app.vue -->
<template>
<div>Hello, World!!</div>
</template>
- 安装依赖
npm i
- 启动项目 (开发环境)
npm run dev
- 打包项目
npm run build
- 启动项目 (生产环境)
npm run start
类型声明
如果你想要开一个 ts 项目
请在根目录下创建 tsconfig.json,并补充 👇
{
"extends": "./.nuxt/tsconfig.json"
}
为了更好的类型提示,还需要在根目录下创建 nuxt.config.ts,并补充 👇
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
typescript: {
shim: false
}
})
插件推荐
安装以下插件可以让你在 vscode 中有更友好的开发体验
自动引入
API
在 composables 目录下模块的同名导出会被自动引入
例如,composables 下有个 useFoo 模块
// composables/useFoo.ts
export const useFoo = 100
<script setup lang="ts">
// useFoo 将被按需自动引入
console.log(useFoo)
</script>
嵌套
如果 API 嵌套在目录内,可以通过 index 模块导出
例如,composables/useDark 下有个 index 模块
// composables/useDark/index.ts
export const useDark = 'yes'
<script setup lang="ts">
// useDark 将被按需自动引入
console.log(useDark)
</script>
内置
vue 和 nuxt3 本身的 api 也支持按需自动引入
<script setup lang="ts">
// ref 将被按需自动引入
const counter = ref(1)
</script>
组件
在 components 目录下的组件将被自动引入
例如,components 下有个 bar 组件
<!-- components/bar.vue -->
<template>
Bar
</template>
<!-- app.vue -->
<template>
Hello, World!
<Bar /> <!-- bar 组件将被按需自动引入并注册 -->
</template>
当然小写也可以
<!-- app.vue -->
<template>
Hello, World!
<bar /> <!-- bar 组件将被按需自动引入并注册 -->
</template>
嵌套
如果组件嵌套在目录内,可以用驼峰式
例如,components/user 下有个 avatar 组件
<!-- components/user/avatar.vue -->
<template>
user avatar
</template>
<!-- app.vue -->
<template>
Hello, World!
<UserAvatar /> <!-- avatar 组件将被按需自动引入并注册 -->
</template>
文件路由
基础
- 在
app.vue中加入NuxtPage
<template>
<NuxtPage />
</template>
- 在
pages下的页面都将被自动路由
例如,/ 页面只需创建 pages/index.vue
<!-- pages/index.vue -->
<!-- 路由 / 将渲染 -->
<template> default </template>
又例如,/home 页面只需创建 pages/home.vue
<!-- pages/home.vue -->
<!-- 路由 /home 将渲染 -->
<template> home </template>
再例如,/about 页面只需创建 pages/about.vue
<!-- pages/about.vue -->
<!-- 路由 /about 将渲染 -->
<template> about </template>
嵌套
如果需要子路由,可以才用目录嵌套的方式
例如,/user/details 页面只需创建 pages/user/details.vue
<!-- pages/user/details.vue -->
<!-- 路由 /user/details 将渲染 -->
<template> user/details </template>
当然你还可以创建 pages/user.vue 来做成嵌套路由
<!-- pages/user.vue -->
<template>
user
<NuxtChild /> <!-- 子路由出口 -->
</template>
动态
如果需要动态路由,可以使用 [param] 的方式
例如,/user/:id 页面只需创建 /pages/user/[id].vue
同时可以通过 $route.params.id 获取到具体的参数
<!-- pages/user/[id].vue -->
<!-- 路由 /user/:id 将渲染 -->
<template>
user / {{ $route.params.id }}
</template>
当然父路由也可以是动态的
例如,/user-:group/:id 页面只需创建 /pages/user-[group]/[id].vue
同时可以通过 $route.params.group 获取到具体的参数
<!-- /pages/user-[group]/[id].vue -->
<!-- 路由 /user-:group/:id 将渲染 -->
<template>
user-{{ $route.params.group }} / {{ $route.params.id }}
</template>
导航
NuxtLink 可以用来导航
<!-- app.vue -->
<template>
<!-- 点击将跳转到 /about 页面 -->
<NuxtLink to="/about"> to about </NuxtLink>
</template>
当然还可以跳转外链
<!-- app.vue -->
<template>
<!-- 点击将跳转到 百度 页面 -->
<NuxtLink to="https://www.baidu.com/"> to baidu </NuxtLink>
</template>
元信息
我们可以通过 definePageMeta 设置当前路由的元信息
<script setup lang="ts">
// 定义元信息
definePageMeta({
foo: 'bar'
})
// 获取当前路由
const route = useRoute()
// 获取元信息
const { meta } = route
console.log(
toRaw(meta) // 输出 { foo: 'bar' }
)
</script>
布局系统
基础
- 在
layouts下创建的布局都可以应用到页面上
例如,创建 layouts/custom.vue 布局
<!-- layouts/custom.vue -->
<template>
<!-- 根元素是必需的 -->
<div>
custom
<slot /> <!-- 页面出口 -->
</div>
</template>
紧接着就可以在页面中使用
例如,在 /home 页面中使用
<!-- pages/home.vue -->
<template>
<NuxtLayout name="custom"> home </NuxtLayout>
</template>
全局
有时我们需要全局的去应用布局,这时对 app.vue 进行修改
<!-- app.vue -->
<template>
header <!-- 这将应用到全局 -->
<NuxtPage />
</template>
但是这是一个无法关闭的全局布局,这时可以删除 app.vue,同时创建 layouts/default.vue 布局
<!-- layouts/default.vue -->
<template>
<div>
header
<slot /> <!-- 页面出口 -->
</div>
</template>
该布局也是全局应用的,但是可以手动关闭
例如 /about 页面不需要该布局
<!-- pages/about.vue -->
<script setup lang="ts">
definePageMeta({
layout: false // 通过元信息的方式关闭 default 布局
})
</script>
<template> about </template>
注意事项
如果你是使用组件的形式去应用其他布局,default 布局将与其他布局重合,那么需要手动关闭。
例如,在 /home 页面中
<script setup lang="ts">
definePageMeta({
layout: false // 手动关闭 default 布局
})
</script>
<template>
<!-- 使用组件的方式应用 custom 布局 -->
<NuxtLayout name="custom"> home </NuxtLayout>
</template>
状态共享
基础
- 使用
useState可以定义简单的共享状态
例如在 composables 中定义 useCounter
// composables/useCounter.ts
// composables 下模块的同名导出将被自动按需引入
export const useCounter = () => useState('counter', () => 100)
useState 的第一参数为 key,第二参数为初始化的工厂函数
此时在 index 页面中可以直接使用 useCounter
<!-- pages/index.vue -->
<script lang="ts" setup>
const conuter = useCounter() // 这是按需自动引入的
</script>
<template>
<div> <!-- 顶层的 div 包裹是必需的,不然跳转会丢失状态 -->
<div @click="conuter++">{{ conuter }}</div>
<NuxtLink to="/home">to home</NuxtLink>
</div>
</template>
home 页面中也可以直接使用
<!-- pages/home.vue -->
<script lang="ts" setup>
const conuter = useCounter()
</script>
<template>
<div @click="conuter++">{{ conuter }}</div>
</template>
你会发现两个页面的状态是共享的 👍
注意
useState 只允许在生命周期中使用。
数据获取
基础
nuxt3 中内置了以下四种请求的方法
- useFetch
- useLazyFetch
- useAsyncData
- useLazyAsyncData
<script setup lang="ts">
// 参数一是 key
// 参数二是请求 handler,返回请求的 promise
// 解构出来的 data 为数据,error 为错误信息
const { data, error } = await useAsyncData('count', () => {
return new Promise(resolve => resolve('mock'))
})
</script>
<template>
<div>
<div>data: {{ data }}</div>
<div>error: {{ error }}</div>
</div>
</template>
内置的 $fetch 可以直接进行请求
<script setup lang="ts">
const { data, error } = await useAsyncData('count', () => {
return $fetch('http://...') // 请求地址
})
</script>
当然你可以用更简洁的 useFetch,它会在内部自动生成 key。
<script setup lang="ts">
const { data, error } = await useFetch('http://...') // 你的请求地址
</script>
useFetch 会在内部自动使用 $fetch 作为请求方法,所以没有 useAsyncData 灵活。
lazy
useFetch 和 useAsyncData 会阻塞导航的跳转。
例如,index 页面跳转到 home 页面
<template>
<NuxtLink to="/home"> to home</NuxtLink>
</template>
而 home 页面有 useFetch 请求
<!-- pages/home.vue -->
<script lang="ts" setup>
// 以下请求将会阻塞导航的跳转
const { data } = await useFetch('http://localhost:4000')
</script>
<template>
<div>{{ data }}</div>
</template>
而使用对应的 lazy 模式,useLazyFetch 或 useLazyAsyncData 可以让导航跳转不被阻塞
<!-- pages/home.vue -->
<script lang="ts" setup>
// 使用 useFetch 的 lazy 模式,不会阻塞导航跳转
const { data } = await useLazyFetch('http://localhost:4000')
</script>
<template>
<div>{{ data }}</div>
</template>
注意
由于 nuxt3 默认是全 SSR 的渲染模式,所以相同的业务代码会在 node 和浏览器都跑一遍。
这意味着大多数 仅支持浏览器的请求库 可能需要被迫在特定生命周期节点中运行。
具体可见 👉 SSR/访问平台特有 API。
因为 axios 兼容 node 和浏览器双端的,所以你能够使用它进行请求。
<script lang="ts" setup>
const { data } = await axios.get('http://...') // 你的请求地址
</script>
不过还是推荐你使用内置请求方法。
频道
接下来也会在 哔哩哔哩 中分享,欢迎关注哦!!
转载自:https://juejin.cn/post/7080007366808666119