前言
时间:2024-10(搭建时间)
开发环境
Node.js - v18.0.0+ (个人版本是18.20.4) 一般选取的版本是**偶数版本**,比如18.x /20.x/22.x
文本编辑器 - 推荐使用 Visual Studio Code (个人版本是1.87.2)
**nuxtjs**版本为 3.11
项目基础依赖
animate.css 4.1.1
nuxt 3.13.0
sass 1.79.4
vue 3.5.12
vue-router 4.4.5
项目搭建及相关配置
项目搭建
(ps:先得安装vs code 和node.js)
首先我们可以新建一个项目,这里我们使用命令npx nuxi@latest init
使用命令后会提示我们使用包管理器,这里我选择npm,一般安装了node.js 会安装npm作为管理器,其他的我本地没有安装这类的包管理器,yarn(一般用linux系统比较多),所以推荐使用npm.
如图可以看到此时正在帮我们安装相关依赖
安装结束后 会提示我们是否初始化git仓库,我这边选择No.
这边告诉我们使用的是v3 template,其实就是基于vue3的template(模板),还很贴心的告诉我们启动开发环境的服务 可以使用命令 :npm run dev
使用vs code打开项目
这里我们可以基于项目根目录,使用“code .”快速打开项目,当然也可以在vs code里面选择项目的根目录
安装项目的扩展和调试配置
第一步:安装扩展
接着我们可以在vs code里面的安装Nuxtr和**Vue - Official (原名Volar) **这两个扩展
安装了Nuxtr这个扩展会出现在vs code左侧下方,在里面可以(build)构建项目/(dev)运行项目等,还可以查看依赖(Dependencies)以及创建文件模板(File Templates)
第二步:在vs code 运行和调试(图标包含个小虫子)处,创建launch.json
接着把如下配置粘进去
{
// 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",
//"runtimeExecutable":"C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "server: nuxt",
"outputCapture": "console",//std or console
// "program": "${workspaceFolder}//.nuxt//dist//server//server.mjs",
"program": "${workspaceFolder}/node_modules/nuxi/bin/nuxi.mjs",
"args": [
"dev"
],
"sourceMaps": true, // 启用源代码映射,这对于调试编译后的代码(如TypeScript)很有用
// "outFiles": [
// "${workspaceFolder}/.nuxt/dist/server/server.js" // 这是Nuxt项目编译后服务器代码的路径,你可能需要根据实际情况修改
// ],
"skipFiles": [
"<node_internals>/**" // 跳过Node.js内部文件的调试
],
"env": {
"NODE_ENV": "development" // 设置环境变量为开发模式
},
},
//先使用npm run dev运行程序 然后找到bin/nuxt.js的程序进行attach
{
"type": "node",
"request": "attach",
"name": "server: nuxt attach",
"processId": "${command:PickProcess}",
"port": 9229
}
],
"compounds": [
{
"name": "fullstack: nuxt",
"configurations": [
"server: nuxt",
"client: chrome"
]
}
]
}
成功后,你可以看到运行和调试处有如下选项,分别是
1.client:chrome 使用浏览器对客户端(其实就是前端代码)调试
2.server:nuxt 调试nuxt服务端
3.fullstack:nuxt 调试所有的nuxt(全栈:包含前后端)
目录结构
package.json里面主要是脚本信息和依赖信息。
tsconfig.json 是ts(typescript的相关配置),目前是继承了基础配置
“extends”: “./.nuxt/tsconfig.json”
nuxt的配置
在nuxt.config.ts中添加
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2024-04-03',
devtools: { enabled: true },
routeRules: {
// 为了SEO目的,在构建时生成
'/': { prerender: true },
// 缓存1小时
'/api/*': { cache: { maxAge: 60 * 60 } },
// 重定向以避免404
'/old-page': {
redirect: { to:'/new-page', statusCode: 302}
}
// ...
},
$production:{
routeRules: {
'/**': { isr: true }
}
},
$development: {
//
},
runtimeConfig: {
// 只在服务器端可用的私有键
apiSecret: '123',
// public中的键也可以在客户端使用
public: {
apiBase: '/api'
}
},
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "@/assets/_colors.scss" as *;'
}
}
}
},
css: ['~/assets/css/main.css', 'animate.css'],
//页面过渡效果 真的所有页面
app: {
pageTransition: { name: 'page', mode: 'out-in' }
},
sourcemap: {
server: true,
client: true
},
})
局部解释
$production: {
routeRules: {
'/**': { isr: true }
}
},
isr: true 允许你在构建网站后创建或更新静态页面,意味着我们运行项目后添加的页面及配置 仍然能生效 不需要重新启动项目
runtimeConfig: {
apiSecret: '123',
public: {
apiBase: '/api'
}
}
在runtimeConfig里面有public - apiBase 这个是后端接口的前缀,如果需要访问接口需要带上api,例如后端接口看起来是127.0.0.1:3000/foo,实际你访问需要访问的是127.0.0.1:3000/api/foo
应用程序配置
这个我们需要在项目根目录下新建一个ts文件: app.config.ts
export default defineAppConfig({
title: 'Hello Nuxt',
theme: {
dark: true,
colors: {
primary: '#ff0000'
}
},
})
app.config.ts 文件用于公开在构建时可以确定的公共变量。与 runtimeConfig 选项相反,这些变量不能使用环境变量覆盖。(这里意味着,以title属性为例在运行期间他是不能被覆盖 被更改的)
nuxt配置(nuxt.config.ts)和应用程序配置(app.config.ts)的区别
如上所述,runtimeConfig和app.config都用于向应用程序的其余部分公开变量。为了确定应该使用其中之一,以下是一些指导原则:
runtimeConfig:需要在构建后使用环境变量指定的私有或公共令牌。
app.config:在构建时确定的公共令牌,网站配置(如主题变体、标题)以及不敏感的项目配置等。
视图
如果我们需要写页面(也可以称之为视图),我们需要在项目根目录下创建文件夹pages,后续的视图都可以写在里面。这边我建立一些视图
我们把鼠标放在pages点击右键,选择New Page.
接着输入页面的名称,不需要带后缀(它会自动带上后缀的),比如我输入了index(回车后),vs code会帮我生成一个index.vue的文件
资源(assets)
Nuxt提供了两种选项来处理你的资源。
Nuxt使用两个目录来处理样式表、字体或图片等资源。
–| public/ 目录中的内容会按原样作为服务器根目录下的公共资源提供。
–| assets/ 目录按约定包含了你希望构建工具(Vite或webpack)处理的所有资源。
公共目录(public folder)
public/ 目录用作应用程序的公共服务器,用于存放在应用程序的指定URL下公开访问的静态资源。
你可以通过应用程序的代码或浏览器的根URL / 获取 public/ 目录中的文件。
资源目录(assert folder)
Nuxt使用 Vite(默认)或 webpack 来构建和打包你的应用程序。这些构建工具的主要功能是处理JavaScript文件,但它们可以通过 插件(对于Vite)或 加载器(对于webpack)来处理其他类型的资源,如样式表、字体或SVG。此步骤主要是为了提高性能或缓存目的而对原始文件进行转换(例如样式表的缩小或浏览器缓存失效)。
按照约定,Nuxt使用 assets/ 目录来存储这些文件,但该目录没有自动扫描功能,你可以使用任何其他名称。
在应用程序的代码中,你可以通过使用 ~/assets/ 路径来引用位于 assets/ 目录中的文件。
在我的public文件夹下 存放了样式(css)、字体、图片。还有个robots.txt这个其实爬虫抓取的协议,大家应该知道百度、谷歌等搜索引擎吧,这个就是跟它们打交道的,告诉它们啥能抓取 啥不能抓取。
从权限上来说 public文件夹的开放性很大,外部一些应用能比较容易访问到其资源,而assert目录刚好相反,私密度较高。
样式
本地样式表
如果你正在编写本地样式表,将它们放在 assets目录下是最自然的位置。
这边我们新建一个first.css,这时我们有两种方式访问到它
方式1:页面中引入first.css
1.1 在javaScript中 import 相关样式 这边有静态和动态导入
1.2 或者使用 css 的 @import 语句
<script>
// 使用静态导入以实现服务器端兼容性
import '~/assets/css/first.css'
// 注意:动态导入不兼容服务器端
import('~/assets/css/first.css')
</script>
<style>
@import url("~/assets/css/first.css");
</style>
方式2:配置全局样式,意味着所有页面都能访问到css
(在nuxt.config.ts中配置如下代码)
export default defineNuxtConfig({
css: ['~/assets/css/first.css']
})
此处仅介绍这两种方式,其他的方式请移步官网。
路由
此次说的路由是页面路由,我们可以看到在pages目录下我新建了四个vue文件
| pages/
---| about.vue
---| index.vue
---| posts/
-----| [id].vue
它形成的路由是这样的
{
"routes": [
{
"path": "/about",
"component": "pages/about.vue"
},
{
"path": "/",
"component": "pages/index.vue"
},
{
"path": "/posts/:id",
"component": "pages/posts/[id].vue"
}
]
}
我们的页面服务启动默认是3000端口,访问页面一般是这样的localhost:3000/about
这边的pages/posts/[id].vue访问风格是相当动态的:
localhost:3000/posts/99
localhost:3000/posts/foo
路由参数
我们可以在页面中 使用typescript,在其中使用useRoute函数,从而访问我们路由参数
<script setup lang="ts">
const route = useRoute()
// 当访问/posts/1时,route.params.id将为1
console.log(route.params.id)
</script>
路由验证
Nuxt通过每个要验证的页面中的definePageMeta()的validate属性提供路由验证。
validate属性接受route作为参数。您可以返回一个布尔值来确定是否将此路由视为有效路由以渲染此页面。如果返回false,并且找不到其他匹配项,这将导致404错误。您还可以直接返回一个带有statusCode/statusMessage的对象以立即响应错误(其他匹配项将不会被检查)。
如果您有更复杂的用例,可以使用匿名路由中间件代替。
<script setup lang="ts">
definePageMeta({
validate: async (route) => {
// 检查id是否由数字组成
return /^\d+$/.test(route.params?.id)
}
})
</script>
服务器
这个部分就涉及了后端了,大家常用的就是http请求。
我们移步到server目录,我们可以在sever新建一个api文件夹,接着我们也可以选中此文件夹,右键可以看到有个New API
我们选择New API 输入名称:test,这时候vs code会帮我们创建test.ts文件
内容也很简单
export default defineEventHandler(async (event) => {
return 'Hello Nitro'
})
接着我们在server\api文件夹中创建 book\[id].ts、book.get.ts、book.post.ts、book.delete.ts 先不要管为什么创建,无脑创建就行了,接着我们使用npm run dev来运行整个项目,然后通过localhost:3000来访问前端
(当然我们也可以使用Nuxtr拓展 点击dev来运行项目也是可以)
然后我们可以看到主界面:
这里忽略我主界面的部分内容,这边呢我们可以看到页面的路由,这边我们选择图片上的部分,选择这个云朵标志的图标,这个就是Server Routes.这个就是我们的服务路由,记录了后端所有的api(请求路由)
接着我们就可以看到一堆请求地址了。
最简单的就是/api/test这个请求了,我们选择发生请求
可以看到一个空的响应。
形成特定请求地址
左侧我们可以选择请求方式,如GET POST PUT DELETE等请求方式。
哎,如果你想你的某个请求只支持GET /POST 请求,该怎么办?不要慌,这里我们在server/api文件夹下创建两个ts文件:book.get.ts 和 book.post.ts
没错,这种命名方式表达(api/book)请求分别拥有get 请求和post请求,其他的我们也可以如法炮制。
假设我需要的路由是api/book/{id} 这种的,我们该怎么办?不要慌,我们可以选择server/api文件夹右键创建API,文件名称为 “book/[id]”,回车后就能生成文件了
这种请求风格是这样的:api/book/123 或 api/book/foo
路由参数获取
首先对于服务路由的文件基本都是这样的,里面有个event参数,包含了request、method等
export default defineEventHandler(async (event) => {
//coding
})
路径上的参数
如果请求地址是:api/book/{id} 这种风格我们可以使用
event.context.params?.id
如果请求地址是:api/book?name=zhaoqiansun&age=29 这种风格我们可以使用
const queryInfo =getQuery(event)
请求体中的参数
可以使用此函数获取请求体中数据
const bodyInfo =readBody(event)
请求至服务器
我们写的服务器接口,基本上都是为了页面请求 获取数据/处理业务。
这边我们写个test.vue页面和test.ts(后端接口)
<script setup lang="ts">
const { data: resultTxt } = await useFetch('/api/test?name=zhaoqian&age=29')
.catch((error) => error.data);
</script>
<template>
<p>当前请求的结果:{{resultTxt}}</p>
</template>
//http://localhost:3000/api/test 返回Hello Nitro
export default defineEventHandler(async (event) => {
const query = getQuery(event) //查询参数
return query??"hello Nuxt";
})
Nuxt 在底层使用 Vue 的 组件,以防止在视图中的每个异步数据可用之前导航。数据获取组合函数可以帮助您利用此功能,并根据每个调用的需求使用最适合的方法。
useFetch
useFetch 组合函数是执行数据获取的最简单的方法。上面我就是使用useFetch请求到接口。
界面效果:
$fetch
Nuxt 包括了 ofetch 库,并且作为全局别名 $fetch 自动导入到应用程序中。它是 useFetch 在幕后使用的工具。
const resultTxt = await $fetch('/api/test?name=zhaoqian&age=29').then(res => res
).catch((error) => error.data);
请注意,仅使用 $fetch 将不会提供 网络请求重复和导航阻止。建议在提交数据到事件处理程序时使用 $fetch,在客户端逻辑中使用,或与 useAsyncData 结合使用。
ofetch 库是基于 Fetch API 构建的,并为其添加了便利功能:
在浏览器、Node 或 worker 环境中的使用方式相同
- 自动解析响应
- 错误处理
- 自动重试
- 拦截器
useAsyncData
useAsyncData 组合函数负责封装异步逻辑并在解析完成后返回结果。
事实上,useFetch(url) 几乎等同于 useAsyncData(url, () => $fetch(url)) - 它是为最常见的用例提供的开发者体验糖。
在某些情况下,使用 useFetch 组合函数是不合适的,例如当 CMS 或第三方提供自己的查询层时。在这种情况下,您可以使用 useAsyncData 来封装您的调用,并仍然保持组合函数提供的好处。
const { data:resultTxt,error } = await useAsyncData('/api/test',()=> {
return $fetch('/api/test?name=zhaoqian&age=29').then(res=>res).catch((error) => error.data);
});
使用Vs Code调试
首先选择运行和调试,创建launch.json文件,然后将配置放入此文件,可以回归“安装项目的扩展和调试配置”章节,此时我们就可以对前后端进行断点调试了
在 Nuxt 3 中,我们可以直接在浏览器和 IDE 中开始调试应用程序。
Sourcemaps
默认情况下,构建启用源映射,并在开发模式下为客户端构建启用源映射,但可以在配置中具体地启用相关配置。
export default defineNuxtConfig({
// or sourcemap: true
sourcemap: {
server: true,
client: true
}
})
Nuxt3.x与Nuxt2.x目录对比
Nuxt2.x 最低需要Node.js 14+ ,NuxtJs3.x和Nuxt2.x需要的基本上都是偶数的Node.js版本,
比如Node.js-14.x Node.js-16.x Node.js-18.x Node.js-20.x 等等
如果你本地版本较低可以尝试使用Nuxt2.x版本,本文的版本是2024年最新的一般,可能不是很适合生产环境,再此出个教程,也是自己学习,告诫自己任何编程语言 无论是web端还是客户端都能被其他的语言平替(至少在java、c#、go、js、python这几门编程中是这样的)
2.x目录
├─components
├─node_modules
├─pages
├─plugins
├─static
├─assert
├─modules =>模块目录
├─middleware=>中间件
└─store ==》文件存储
3.x目录
├─components/*- 扩展默认组件
├─composables/*- 扩展默认可组合项
├─layouts/*- 扩展默认布局
├─pages/*- 扩展默认页面
├─plugins/*- 扩展默认插件
├─server/*- 扩展默认服务器端点和中间件
├─utils/*- 扩展默认 utils
├─nuxt.config.ts- 扩展默认的 nuxt 配置
├─app.config.ts- 扩展默认应用配置
ps:nuxtJs2.x框架 建议使用node.js版本为16.20.2及以上
更多
官方文档:https://nuxtjs.org.cn/docs/getting-started/introduction
手把手教你搭建NuxtJs框架(一)之使用jwt进行鉴权