超详细的 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