1.Nest.js 和 Next.js
结合 Nest.js 和 Next.js 可以构建强大的全栈应用程序,将前端和后端无缝集成在一起。这种组合可以带来一些好处:
- 统一的技术栈:Nest.js 和 Next.js 都是基于 JavaScript/TypeScript 的框架,它们使用相似的语法和开发模式,使得开发人员可以在前后端之间共享代码和知识。这种一致性可以减少学习成本和开发难度。
- 前后端协同开发:Nest.js 和 Next.js 都提供了模块化组织和依赖注入等特性,使得团队可以更好地协同开发。前端和后端开发人员可以在同一项目中并行工作,更好地沟通和协调。
- 服务器渲染和静态网站生成:Next.js 提供了服务器渲染 (SSR) 和静态网站生成 (SSG) 的功能,使得页面的首次加载速度更快,并提供更好的 SEO。结合 Nest.js,你可以在服务器端使用 Nest.js 的路由和控制器来处理页面渲染的逻辑。
- 一体化部署:由于 Nest.js 和 Next.js 都可以在 Node.js 环境下运行,你可以将前后端代码打包在一起,并将整个应用程序部署到同一个服务器或容器中,简化部署和维护过程。
当然,结合 Nest.js 和 Next.js 也会带来一些挑战。例如,需要更多的配置和集成工作,需要合理规划前后端的职责和交互,以及处理好数据传递和状态管理等问题。此外,使用这种组合也需要对 Nest.js 和 Next.js 的特性和用法有一定的了解。
综上所述,Nest.js 和 Next.js 的组合可以为全栈应用程序开发带来许多好处,但也需要权衡和适应相应的开发需求和挑战。
Nest.js 是一个用于构建高度可扩展、模块化和松耦合的服务器端应用程序的框架。它基于 TypeScript,并采用了面向对象 (OOP)、函数式编程 (FP) 和响应式编程 (Reactive Programming) 等编程范式。Nest.js 提供了强大的依赖注入 (Dependency Injection)、模块化组织、路由和中间件等功能,使得构建复杂的后端应用程序变得更加简单和可维护。Nest.js 还支持多种数据库和消息队列的集成,并提供了一套完整的测试工具和生命周期钩子等功能。
Nest.js 不是直接替代 Koa 的方案,而是在 Express 或 Fastify 的基础上构建的一个框架。Nest.js 提供了一种用于构建服务器端应用程序的高级抽象层,它在底层使用了 Express 或 Fastify 作为 HTTP 服务器的引擎。
Next.js 是一个用于构建 React 应用程序的轻量级框架。它主要用于构建基于服务器渲染 (Server-Side Rendering, SSR) 和静态网站生成 (Static Site Generation, SSG) 的应用程序。Next.js 提供了简单的文件系统路由、预渲染、数据预取等功能,使得构建响应式和高性能的应用程序变得更加容易。它还支持热模块替换 (Hot Module Replacement, HMR),使开发人员可以在不刷新整个页面的情况下实时预览和调试应用程序。
2.解构赋值设置默认值
解构赋值语法中,可以使用赋值运算符(=)为解构的变量设置默认值。如果解构的对象中对应的属性不存在或者其值为 undefined,那么默认值将被使用。
以下是一个示例:
const person = {
name: 'John',
age: 30
};
// 解构赋值并设置默认值
const { name, profession = 'Unknown', age } = person;
console.log(name); // 输出: 'John'
console.log(profession); // 输出: 'Unknown' (person 对象中没有 profession 属性,使用默认值)
console.log(age); // 输出: 30
在上述示例中,person
对象中的属性 name
和 age
被解构赋值给变量 name
和 age
。而属性 profession
并不存在于 person
对象中,因此解构赋值时使用了默认值 'Unknown'
,将其赋给变量 profession
。
这样,即使原对象中缺少某些属性,也可以通过设置默认值来确保解构赋值不会导致变量的值为 undefined
。
3.substr()
、substring()
和 slice()
substr()
、substring()
和 slice()
是 JavaScript 字符串方法,用于从一个字符串中提取子字符串。它们之间的区别如下:
substr(start, length)
: 从指定的起始索引位置开始,提取指定长度的子字符串。第一个参数start
表示起始索引,可以是负数(表示从字符串末尾开始计算)。第二个参数length
表示要提取的子字符串的长度。如果省略第二个参数length
,则提取从起始索引到字符串末尾的所有字符。需要注意的是,substr()
方法在处理负数参数时与slice()
方法不同,它将负数参数转换为 0。substring(start, end)
: 从指定的起始索引位置开始,提取到指定的结束索引位置之前的子字符串。第一个参数start
表示起始索引,可以是负数(表示从字符串末尾开始计算)。第二个参数end
表示结束索引(不包括该索引处的字符)。如果省略第二个参数end
,则提取从起始索引到字符串末尾的所有字符。需要注意的是,如果start
大于end
,substring()
方法会交换这两个参数的值。slice(start, end)
: 从指定的起始索引位置开始,提取到指定的结束索引位置之前的子字符串。第一个参数start
表示起始索引,可以是负数(表示从字符串末尾开始计算)。第二个参数end
表示结束索引(不包括该索引处的字符)。如果省略第二个参数end
,则提取从起始索引到字符串末尾的所有字符。与substring()
不同,slice()
方法允许start
大于end
,并且不会交换参数的位置,它会从索引end
开始提取子字符串,直到索引start
(不包括start
处的字符)为止。
需要注意的是,这三个方法在处理负数索引时的行为略有不同。substr()
将负数索引转换为 0,而 substring()
和 slice()
将负数索引视为从字符串末尾开始的位置。
总结来说,这些方法的区别在于对负数索引和参数处理的不同。如果需要根据起始索引和长度提取子字符串,可以使用 substr()
。如果需要根据起始索引和结束索引提取子字符串,可以使用 substring()
或 slice()
。建议优先使用 slice()
,因为它的行为更一致和直观,并且可以处理更多的情况,例如允许 start
大于 end
。
注意:substr已经被废弃,最推荐 slice
4.sort排序数组
不传参数,直接使用
JavaScript 中的 sort()
方法用于对数组元素进行排序。它会就地修改原始数组,将数组元素重新排序,并返回排序后的数组。
sort()
方法默认按照字符串的 Unicode 编码进行排序。也就是说,它会将数组元素转换为字符串,然后按照字符串的字母顺序进行排序。这可能不会按照数字的预期顺序进行排序。
以下是 sort()
方法的基本用法示例:
var arr = [3, 1, 5, 2, 4];
arr.sort();
console.log(arr); // 输出 [1, 2, 3, 4, 5]
当你在 sort()
方法中传入回调函数时,该回调函数会被用作自定义的排序规则。回调函数接受两个参数,表示要进行比较的两个元素。
sort 排序数字列表不准确!不要不传回调!
数字列表可能会按照字符串的字典顺序进行排序,而不是按照数字的大小顺序进行排序。例如,[10, 2, 5, 1]
可能会被排序为 [1, 10, 2, 5]
。
为了正确地对数字列表进行排序,你可以传递一个自定义的比较函数作为 .sort()
方法的参数。
以下是一个示例,演示了如何使用自定义比较函数对数字列表进行排序:
var arr = [10, 2, 5, 1];
arr.sort(function(a, b) {
return a - b; // 升序排序
});
console.log(arr); // 输出 [1, 2, 5, 10]
逆序排序:
var arr = [3, 1, 5, 2, 4];
arr.sort(function(a, b) {
return b - a; // 逆序排序
});
console.log(arr); // 输出 [5, 4, 3, 2, 1]
注意:尽量不要直接用sort()不传参的方式去调用,只要用就一定自己定义规则!
注意:当你对字符串数组使用不传参的 .sort()
方法进行排序时,它会按照字符串的首字母顺序进行排序。——> 唯一不传参的时候好用的情况!
var arr = ['banana', 'apple', 'orange', 'grape'];
arr.sort();
console.log(arr); // 输出 ["apple", "banana", "grape", "orange"]
传递回调函数,自定义排序规则
回调函数可以返回负数、零或正数来指示元素之间的相对顺序。如果返回负数,表示第一个元素应该在第二个元素之前;如果返回零,表示两个元素的顺序不变;如果返回正数,表示第二个元素应该在第一个元素之前。(负数不一定是-1,如果返回的是负数那么就说明顺序正确,不需要改变!如果返回的是正数那么就需要调换二者顺序!)
底层的比较应该是不断进行两两比较,直到所有的比较都返回负数为止!
示例 1:以下是一个示例,展示了如何传入回调函数来自定义排序规则:根据奇偶性排序,偶数在前面!
var arr = [3, 1, 5, 2, 4];
arr.sort(function(a, b) {
// 根据元素的奇偶性进行排序
return a % 2 - b % 2;
});
console.log(arr); // 输出 [2, 4, 1, 3, 5]
在上述示例中,我们传入了一个回调函数作为 sort()
方法的参数。这个回调函数根据元素的奇偶性进行排序。通过返回 a % 2 - b % 2
,我们让偶数元素在奇数元素之前。
示例 2:根据对象列表的某一个字段status的数字大小排序,小的在前面!
// 对象列表
var objList = [
{ status: 2 },
{ status: 1 },
{ status: 0 },
{ status: 3 }
];
// 按照 status 字段进行排序
objList.sort((a, b) => {
if (a.status < b.status) {
return -1;
}
if (a.status > b.status) {
return 1;
}
return 0;
});
// 打印排序后的结果
console.log(objList);
示例 3:自定义顺序,根据对象列表的某一个字段让为1的在为0的前面,为0的在为2的前面(只有 0,1,2 这三种值的情况)
// 对象列表
var objList = [
{ status: 2 },
{ status: 1 },
{ status: 0 },
{ status: 1 },
{ status: 2 },
];
// 按照 status 字段进行排序
objList.sort((a, b) => {
if (a.status === 1 && b.status !== 1) {
return -1;
}
if (a.status !== 1 && b.status === 1) {
return 1;
}
if (a.status === 0 && b.status === 2) {
return -1;
}
if (a.status === 2 && b.status === 0) {
return 1;
}
return 0;
});
// 打印排序后的结果
console.log(objList);
实现对一个正序数字数组的逆序
var arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // 输出 [5, 4, 3, 2, 1]
5.Header 中的Content-Type
"Content-Type" 是一个 HTTP 标头字段,用于指定请求或响应的主体内容的类型。它告诉服务器或客户端如何解析和处理主体数据。
以下是一些常见的 "Content-Type" 类型:
- "application/json":用于指定请求或响应的主体内容是 JSON 格式。这是在现代 Web 开发中广泛使用的类型,常用于 API 请求和响应的数据传输。
- "application/x-www-form-urlencoded":用于指定请求主体内容以 URL 编码的表单参数形式传输。这种类型常用于 HTML 表单的默认提交方式。
- "multipart/form-data":用于指定请求主体内容采用多部分的形式传输,通常用于上传文件和表单数据的同时提交。
- "text/html":用于指定请求或响应的主体内容是 HTML 文档。
- "text/plain":用于指定请求或响应的主体内容是纯文本格式。
- "image/jpeg"、"image/png"、"image/gif":用于指定请求或响应的主体内容是相应的图像文件类型。
除了上述类型外,还有许多其他的 "Content-Type" 类型,用于指定不同的数据格式和媒体类型。在进行网络请求或处理服务器响应时,根据实际需求和数据格式,选择适当的 "Content-Type" 类型是很重要的。
application/x-www-form-urlencoded
假设有一个 HTTP POST 请求,要将表单数据作为 URL 编码的形式发送给服务器。以下是一个简单的示例:
请求头部:
POST /api/form-data HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
请求主体:
name=John+Doe&age=25&email=johndoe@example.com
6.web 开发的三种请求参数类型和对应的 content-type
在 Web 开发中,常见的请求参数传递方式包括三种:查询参数、路径参数和请求体参数。
- 查询参数(Query Parameters):查询参数是通过在 URL 中以
?
开头,参数键值对以key=value
的形式拼接在 URL 后面,多个参数之间使用&
连接。例如:http://example.com/api?param1=value1¶m2=value2
。在 Express 中,可以使用req.query
来获取查询参数。在 Spring Boot 中,可以使用@RequestParam
注解来获取请求体参数 - 路径参数(Path Parameters):路径参数是将参数直接嵌入到 URL 路径中的一部分。在 Express 中,可以使用路由参数:或 Spring Boot 中的
@PathVariable
注解来获取路径参数。 - 请求体参数(Request Body Parameters):请求体参数是通过请求主体(body)发送的数据,通常用于 POST、PUT、PATCH 等请求方法。常见的数据格式包括 JSON、表单数据(form data)等。在 Express 中,可以使用中间件如
express.json()
(json格式)和express.urlencoded()
(以 URL 编码的表单参数格式) 来解析请求体参数;在 Spring Boot 中,可以使用@RequestBody
(json格式)和@RequestParam
(以 URL 编码的表单参数格式)来获取请求体参数。
注意:@RequestParam
注解可以同时用于获取表单数据和查询参数。在 Spring Boot 中,可以使用 @RequestParam
注解来获取 URL 查询参数,也可以用于获取 "application/x-www-form-urlencoded" 格式的表单数据。
需要注意的是,这些传递方式并不是互斥的,可以根据实际需求和场景选择合适的方式来传递参数。在 RESTful API 设计中,常常使用路径参数来表示资源的唯一标识,查询参数用于过滤和排序,请求体参数用于传递更复杂的数据结构。
总结起来,查询参数、路径参数和请求体参数是常见的请求参数传递方式,每种方式有其适用的场景和优势。具体选择哪种方式取决于你的项目需求和设计约定。
这三种常见的请求参数传递方式在 Content-Type 方面一般对应如下:
- 查询参数(Query Parameters):查询参数是将参数以键值对的形式直接附加在 URL 后面,不需要指定 Content-Type。查询参数是通过 URL 的查询字符串传递的,例如:
http://example.com/api?param1=value1¶m2=value2
。 - 路径参数(Path Parameters):路径参数通常不涉及 Content-Type。路径参数是将参数直接嵌入到 URL 路径中的一部分,例如:
http://example.com/api/param1/value1/param2/value2
。路径参数的传递不需要指定特定的 Content-Type,它们是通过 URL 的不同部分来传递的。 - 请求体参数(Request Body Parameters):请求体参数的传递方式取决于所发送的数据格式。常见的数据格式及对应的 Content-Type 如下:
- JSON 数据:当请求体参数是以 JSON 格式传递时,通常使用 Content-Type 为 "application/json"。
- 表单数据(form data):当请求体参数是以表单数据形式传递时,通常使用 Content-Type 为 "application/x-www-form-urlencoded" 或 "multipart/form-data"。
需要注意的是,Content-Type 是用来标识请求或响应主体中数据的媒体类型,而不是用来表示请求参数的传递方式。查询参数和路径参数是通过 URL 传递的,而请求体参数是作为请求主体的一部分发送的。
根据实际需求和使用场景,可以选择合适的 Content-Type 和传递方式来传递参数。在请求头部中使用正确的 Content-Type 标头可以确保服务器端能够正确解析和处理请求参数的数据。
表单数据(form data)和查询参数的格式非常类似!
表单数据(form data)和查询参数的格式在某种程度上是相似的,都使用了键值对的形式来传递数据。然而,它们在传递数据的方式和使用场景上有一些区别。
查询参数通常用于 GET 请求,并将参数以键值对的形式直接附加在 URL 的查询字符串中,例如:http://example.com/api?param1=value1¶m2=value2
。查询参数主要用于对资源进行筛选、排序和过滤,可以通过 URL 直接访问和共享。
表单数据(form data)则主要用于 POST 请求,将数据作为请求主体的一部分发送给服务器。在表单数据中,键值对被编码为名称和值之间使用等号(=)连接,多个键值对之间使用与号(&)分隔,例如:param1=value1¶m2=value2
。表单数据通常用于向服务器提交更复杂的数据,如表单提交、文件上传等。
虽然查询参数和表单数据的格式相似,都是使用键值对进行数据传递,但它们的传递方式、使用场景和处理方式是不同的。查询参数是直接附加在 URL 中的,而表单数据则是作为请求主体的一部分发送的。
axios 发送表单参数的请求
import axios from 'axios';
//const formData = 'param1=value1¶m2=value2'; //手动序列化参数为字符串(也可以用URLSearchParams对象来做,也就是构建一个这样的 formdata) ——> 就是一个a=1&b=2的格式
const formData = new URLSearchParams();
formData.append('param1', 'value1');
formData.append('param2', 'value2');
axios.post('/api/data', formData, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(response => {
// 请求成功处理
})
.catch(error => {
// 请求失败处理
});
7.原生form发送表单数据格式请求
使用原生表单实现和上面 axios一样的效果:
HTML 表单通过浏览器默认的表单提交行为来发送请求。当用户点击表单中的提交按钮时,浏览器会收集表单中的数据,并将其作为请求的参数发送到服务器。
以下是一个简单的 HTML 表单示例:
<form action="/api/data" method="POST">
<input type="text" name="param1" value="value1">
<input type="text" name="param2" value="value2">
<button type="submit">Submit</button>
</form>
在上述示例中,<form>
元素表示一个表单,action
属性指定了目标 URL 为 "/api/data",method
属性指定了请求的方法为 POST。
<input>
元素用于接收用户的输入数据,name
属性指定了参数名,value
属性指定了默认的值。
当用户点击表单中的提交按钮时,浏览器会将表单数据作为请求的参数,以 "application/x-www-form-urlencoded" 格式发送到服务器的目标 URL。
我们可以看到上面的 form 表单请求方式为 post ——> 对应的参数类型为:请求体参数,并且格式为application/x-www-form-urlencoded
如果是 get 方式的表单呢?——> 对应的参数类型为:查询参数
对于 GET 方法,表单数据可以通过 URL 的查询字符串来传递参数。当用户点击提交按钮时,浏览器会将表单数据附加到目标 URL 的查询字符串中,然后跳转到该 URL。
以下是一个示例,展示如何在 GET 方法中使用表单传递参数:
<form action="/api/data" method="GET">
<input type="text" name="param1" value="value1">
<input type="text" name="param2" value="value2">
<button type="submit">Submit</button>
</form>
在上述示例中,表单的 action
属性指定了目标 URL 为 "/api/data",使用 GET 方法提交。
<input>
元素用于接收用户的输入数据,name
属性指定了参数名,value
属性指定了默认的值。
当用户点击表单中的提交按钮时,浏览器会将表单数据附加到目标 URL 的查询字符串中,例如:/api/data?param1=value1¶m2=value2
。然后,浏览器会跳转到该 URL,将查询字符串作为 GET 请求的参数发送给服务器。