1.安装
- Node 版本要求 Node.js -
v18.0.0
or newer
# 创建一个新项目
npx nuxi@latest init <project-name>
or
pnpm dlx nuxi@latest init <project-name>
or
bunx nuxi@latest init <project-name>
2.配置
# 配置文件
export default defineNuxtConfig({
// My Nuxt config
})
2.1views
- 根据
/pages/
中文件目录结构生成路由
# 入口文件
app.vue
2.2Components
# 组件放在目录 components/,这些组件可以被用在页面和其他组件中,
以往我们使用这些组件需要导入并注册它们,
但Nuxt会自动导入`components/`目录中的任意组件
-
组件名称约定
没有嵌套的组件会以文件名直接导入,但如果存在嵌套关系哪?例如下面的路径:
| components/
--| base/
----| foo/
------| Button.vue
那么组件名称将会基于路径和文件名连起来,比如上面的base/foo/Button.vue
注册名称将会是BaseFooButton
,将来用起来会像下面这样:
<BaseFooButton />
2.3Assets
静态资源
# 如果使用的图片文件在 public/img/目录:
<img src="/img/nuxt.png" alt="Discover Nuxt 3" />
# 如果使用的图片文件在 assets/目录:
<img src="~/assets/img/nuxt.png" alt="Discover Nuxt 3" />
2.4全局样式配置
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "~/assets/_colors.scss" as *;'
}
}
}
}
})
2.5导入样式文件在组件中
<script>
// Use a static import for server-side compatibility
import '~/assets/css/first.css'
// Caution: Dynamic imports are not server-side compatible
import('~/assets/css/first.css')
</script>
<style>
@import url("~/assets/css/second.css");
</style>
2.6在配置文件中使用css
export default defineNuxtConfig({
css: ['~/assets/css/main.css']
})
2.7使用外部样式
export default defineNuxtConfig({
app: {
head: {
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
}
}})
2.8动态添加
useHead({
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
})
2.9组件内使用
<script setup lang="ts">
const activeColor = ref('red')
const fontSize = ref(30)
const styleObject = reactive({ color: 'red', fontSize: '13px' })
</script>
<template>
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<div :style="[baseStyles, overridingStyles]"></div>
<div :style="styleObject"></div>
</template>
3.Routing
通过useRoute()获取路由信息
<script setup lang="ts">
const route = useRoute()
// When accessing /posts/1, route.params.id will be 1
console.log(route.params.id)
</script>
- 目录
| pages/
---| about.vue
---| index.vue
---| posts/
-----| [id].vue
- 路由参数校验
<script setup lang="ts">
definePageMeta({
validate: async (route) => {
// Check if the id is made up of digits
return /^\d+$/.test(route.params.id)
}
})
</script>
-
动态路由
如果我们在文件名或者文件夹名称里面包含了`方括号`,它们将被转换为`动态路由`参数。
比如:
-| pages/
---| users-[group]/
-----| [id].vue
通过 `/users-admins/123` 导航即可:
- 嵌套路由
比如下面目录结构:
-| pages/
---| parent/
------| child.vue
---| parent.vue
child.vue
<template>
<div>
<h1>child page</h1>
</div>
</template>
父组件中使用NuxtChild组件显示嵌套子组件内容,parent.vue:
<template>
<div>
<h1>parent page</h1>
<!-- 子组件出口 -->
<NuxtChild></NuxtChild>
</div>
</template>
试一下,index.vue
<NuxtLink to="/parent/child">Parent</NuxtLink>
4.fetch
数据请求:
useFetch
,useAsyncData
、$fetch
useFetch
<script setup lang="ts">
const { data: count } = await useFetch('/api/count')
</script>
<template>
Page visits: {{ count }}
</template>
-------------------------
<script setup lang="ts">
const { pending, data: posts } = useFetch('/api/posts', {
lazy: true
})
</script>
<template>
<!-- you will need to handle a loading state -->
<div v-if="pending">
Loading ...
</div>
<div v-else>
<div v-for="post in posts">
<!-- do something -->
</div>
</div>
</template>
4.1$fetch
const users = await $fetch('/api/users').catch((error) => error.data)
4.2useAsyncData
const id = ref(1)
const { data, error } = await useAsyncData(`user:${id.value}`, () => {
return myGetFunction('users', { id: id.value })
})
也可以使用
useLazyFetch
anduseLazyAsyncData
5.环境变量配置
5.1 env
# 新建两个文件
.env.development
.env.production
//package.json
"dev": "nuxt dev --dotenv .env.development",
"build": "nuxt build --dotenv .env.production",
//nuxt.config.ts
// 添加运行时配置
runtimeConfig: {
apiSecret: process.env.NUXT_API_SECRET,
public: {
apiBase: process.env.NUXT_PUBLIC_API_BASE || SERVER_BASE_API,
}
}
---------------------------------------------------------------------
// 如果存在跨域
nitro: {
devProxy: {
'/api': {
target: process.env.NUXT_PUBLIC_API_BASE,
changeOrigin: true,
}
}
}
6.自动导入和调试
不用import可以直接使用 vue3 的api,例如:
ref和 computed
<script setup lang="ts">
const count = ref(1) // ref is auto-imported
</script>
[
components/
], [composables/
] and [utils/
]这几个目录中的会自动导入
- 不想自动导入:nuxt.config.ts
export default defineNuxtConfig({
imports: {
autoImport: false
}
})
添加 nuxt 模块-nuxt.config.ts
export default defineNuxtConfig({
modules: [
// Using package name (recommended usage)
'@nuxtjs/example',
// Load a local module
'./modules/example',
// Add module with inline-options
['./modules/example', { token: '123' }]
// Inline module definition
async (inlineOptions, nuxt) => { }
]
})
调试配置
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "client: chrome",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "server: nuxt",
"outputCapture": "std",
"program": "${workspaceFolder}/node_modules/nuxi/bin/nuxi.mjs",
"args": [
"dev"
],
}
],
"compounds": [
{
"name": "fullstack: nuxt",
"configurations": [
"server: nuxt",
"client: chrome"
]
}
]
}
7.数据请求
建议在获取组件数据时使用
useFetch
或useAsyncData
+$fetch
来防止重复获取数据。
服务器路由
~/server/api
目录中的文件会自动在其路由中添加/api
前缀。
要添加没有/api
前缀的服务器路由,请将它们放入~/server/routes
目录中。
服务器中间件
Nuxt会自动读取~/server/middleware
目录中的任何文件,以创建项目的服务器中间件。
中间件处理程序将在任何其他服务器路由之前在每个请求上运行,以添加或检查标头、记录请求或扩展事件的请求对象。
中间件处理程序不应返回任何内容(也不应关闭或响应请求),只能检查或扩展请求上下文或抛出错误
- server/middleware/log.ts
export default defineEventHandler((event) => {
console.log('New request: ' + getRequestURL(event))
})
- server/middleware/auth.ts
export default defineEventHandler((event) => {
event.context.auth = { user: 123 }
})
匹配HTTP方法
处理文件名可以使用.get
、.post
、.put
、.delete
等后缀来匹配请求的HTTP方法。
server/api/test.get.ts
export default defineEventHandler(() => 'Test get handler')
server/api/test.post.ts
export default defineEventHandler(() => 'Test post handler')
在上面的示例中,使用以下方式获取/test
:
- GET方法:返回
Test get handler
- POST方法:返回
Test post handler
封装请求
- 新建
request.ts
文件,用于编写封装代码
我选择在composables
目录中新建request.ts
。composables
是官方默认的插件目录,官方描述:Nuxt 3使用composables/
目录使用auto-imports自动将Vue组合导入到应用中!
$fetch
重复发送请求问题
- 设置:watch: false
- github.com/nuxt/nuxt/i…
const res = await useFetch('/api/hospital/list', { method: 'POST', body: filterData, watch: false });
server/api内使用
- defineEventHandler
使用 defineEventHandler 可以让我们更方便地定义和管理这些事件处理器函数。它接收两个参数:
- logic: 这是一个函数,用于定义事件处理器的逻辑。该函数接收一个参数,也就是事件对象(例如鼠标点击事件的 event 对象)。在该函数中,我们可以根据传入的参数执行相应的逻辑,然后返回一个结果(如 promise 或其他数据)。
- options: 这是一个可选的参数对象,用于配置该事件处理器函数的行为。它可以包含以下属性:
- once: 如果该属性为 true,则该事件处理器函数只会执行一次。默认值为 false。
- defer: 如果该属性为 true,则该事件处理器函数将在下一轮事件循环中执行。默认值为 false。
export default defineEventHandler((event) => {
const pramObj = getQuery(event) as FilterObj
return fetchHospital(pramObj)
})
使用elementplus分页器文案中文
其中layout用来指定分页元件的布局,即定义展示的分页元件及其展示顺序,元件定义如下:
prev:上一页的按钮。
pager:页码列表。
next:下一页的按钮。
jumper:跳转到。
total:数据总条数。
sizes:每页显示的数据条数/分页大小。
->:该元件将其右侧的元件包裹起来,整体靠右对齐。
slot: 额外自定义内容插槽。
其中,各元件用逗号分隔。
layout的值的顺序决定了元件显示的位置,比如:
layout="total,prev, pager, next,->,jumper,sizes"
这个设置的分页组件元件将按照layout顺序布局
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
const locale = zhCn
<el-config-provider :locale="locale">
<el-pagination
v-model:current-page="resultData.pageNo"
v-model:page-size="resultData.pageSize"
:page-sizes="[10, 20, 30, 40]"
:disabled="disabled"
background
layout="total, prev, pager, next, sizes, jumper"
:total="400"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-config-provider>
遇到的问题
1.使用pnpm install后运行报错
__vite_ssr_import_2__.createMemoryHistory is not a function
后面使用npm install
2.npm i 报错依赖版本不一致时处理
npm install --legacy-peer-deps