~~博主说学vue之前要先学这玩意儿,不懂那学学吧~~

以下内容部分实例代码参考了dengruicode.com的内容

ECMAScript 的背景

JavaScript 是大家所了解的语言名称,但是这个语言名称是商标( Oracle 公司注册的商标)。因此,JavaScript 的正式名称是 ECMAScript 。1996年11月,JavaScript 的创造者网景公司将 JS 提交给国际化标准组织 ECMA(European computer manufactures association,欧洲计算机制造联合会),希望这种语言能够成为国际标准,随后 ECMA 发布了规定浏览器脚本语言的标准,即 ECMAScript。这也有利于这门语言的开放和中立。

ECMAScript 的历史

ES6 是 ECMAScript 标准十余年来变动最大的一个版本,为其添加了许多新的语法特性。

  • 1997 年 ECMAScript 1.0 诞生。
  • 1998 年 6 月 ECMAScript 2.0 诞生,包含一些小的更改,用于同步独立的 ISO 国际标准。
  • 1999 年 12 月 ECMAScript 3.0诞生,它是一个巨大的成功,在业界得到了广泛的支持,它奠定了 JS 的基本语法,被其后版本完全继承。直到今天,我们一开始学习 JS ,其实就是在学 3.0 版的语法。
  • 2000 年的 ECMAScript 4.0 是当下 ES6 的前身,但由于这个版本太过激烈,对 ES 3 做了彻底升级,所以暂时被”和谐”了。
  • 2009 年 12 月,ECMAScript 5.0 版正式发布。ECMA 专家组预计 ECMAScript 的第五个版本会在 2013 年中期到 2018 年作为主流的开发标准。2011年6月,ES 5.1 版发布,并且成为 ISO 国际标准。
  • 2013 年,ES6 草案冻结,不再添加新的功能,新的功能将被放到 ES7 中;2015年6月, ES6 正式通过,成为国际标准。

ES6 的目标与愿景

成为更好编写的开发语言有以下目标。

适应更复杂的应用;实现代码库之间的共享;不断迭代维护新版本。

开始学习

集合

set

Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。

ps:跟c++里面那个标准库里的那个set不太一样,c++的那个是自带排序的

实例

1
2
3
4
const set = new Set([1, 2, 3]);  
for (const value of set) {
console.log(value);
}
1
2
3
4
5
6
7
8
9
//使用for...of循环遍历 Set集合
for (let item of fruits) {
console.log("for...of", item)
}

//使用forEach方法来遍历 Set集合
fruits.forEach(value => {
console.log("forEach", value)
})

map

存储键值对

实例:

1
2
3
4
5
let person = new Map([
["name", "邓瑞"],
["gender", "男"],
["web", "dengruicode.com"]
])
1
2
3
4
//使用forEach方法遍历Map集合的键值对
person.forEach((value, key) => {
console.log("forEach", key, value)
})

对象

私有属性、存取器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Person {
name
#web //私有属性是指仅在类内部可访问和操作的属性, 外部无法直接访问和修改,需用到下面两种取存器

constructor(name, web) {
this.name = name
this.#web = web
}

//使用存取器 getter 获取私有属性
get web() {
return this.#web
}

//使用存取器 setter 设置私有属性
set web(value) {
this.#web = value
}

info() {
return `姓名:${this.name} 个人网站:${this.web}`
}
}

let person = new Person("邓瑞", "dengruicode.com")

console.log("person", person)
console.log("web", person.web) //使用存取器 getter 获取私有属性
console.log("info", person.info())

person.web = "www.dengruicode.com" //使用存取器 setter 设置私有属性
console.log("web", person.web)

类的继承extends

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//父类
class Person {
name
gender

constructor(name, gender) {
this.name = name
this.gender = gender
}

sleep() {
return `${this.name} 休息中...`
}
}

//子类
class David extends Person {
web

constructor(name, gender, web) {
super(name, gender) //调用父类构造函数

this.web = web
}

eat() {
return `${this.name} 正在吃饭...`
}
}

let david = new David("邓瑞", "男", "dengruicode.com")

console.log("david", david)
console.log("web", david.web)
console.log("eat", david.eat())

console.log("gender", david.gender)
console.log("sleep", david.sleep())

解构

这是一种表达式,允许从数组或对象中提取数据,并将提取的数据赋值给声明的变量。这种方法可以使代码更加简洁和易于理解。

数组解构

基本用法

1
2
let [x, y] = [1, 2];
console.log("x:", x, "y:", y); // 输出: x: 1 y: 2

这里,数组[1, 2]中的第一个元素赋值给了变量x,第二个元素赋值给了变量y

跳过某些元素

1
2
let [, , c] = [10, 20, 30];
console.log("c:", c); // 输出: c: 30

这里,数组中的第一个和第二个元素被跳过,第三个元素赋值给了变量c

扩展运算符

1
2
let [A, ...B] = [1, 2, 3, 4, 5, 6];
console.log("A:", A, "B:", B); // 输出: A: 1 B: [2, 3, 4, 5, 6]

这里,数组的第一个元素赋值给了变量A,剩余的元素组成了一个新的数组赋值给了变量B

默认值

1
2
let [x2, y2 = 200] = [100];
console.log("x2:", x2, "y2:", y2); // 输出: x2: 100 y2: 200

如果数组解构时某个位置没有对应的值,则可以使用默认值。这里y2的默认值是200

两数交换

1
2
3
4
let x3 = 10;
let y3 = 20;
[x3, y3] = [y3, x3];
console.log("x3:", x3, "y3:", y3); // 输出: x3: 20 y3: 10

通过数组解构,可以很方便地交换两个变量的值。

对象解构

基本用法

1
2
let { name } = person;
console.log("name:", name); // 输出: name: 邓瑞

从对象person中提取name属性的值,并赋值给变量name

重命名

1
2
let { name: userName, gender, web } = person;
console.log("userName:", userName, "gender:", gender, "web:", web); // 输出: userName: 邓瑞 gender: 男 web: dengruicode.com

这里,将name属性的值赋给了变量userName,同时提取了genderweb属性的值。

默认值

1
2
let { address = "安徽" } = person;
console.log("address:", address); // 输出: address: 安徽

如果对象解构时某个属性不存在,则可以使用默认值。这里person对象中没有address属性,所以address的默认值是"安徽"

解构赋值是ES6引入的一个非常有用的特性,它使得从数组或对象中提取数据变得更加直观和简洁。

字符串常见函数方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
let web = "dengruicode.com";  

// 字符串长度
let len = web.length;
console.log("字符串长度:", len); // 输出: 字符串长度: 14

// 转小写
let str1 = "DAVID".toLowerCase();
console.log("转小写:", str1); // 输出: 转小写: david

// 转大写
let str2 = "luna".toUpperCase();
console.log("转大写:", str2); // 输出: 转大写: LUNA

// 返回字符串在索引处的字符
let str3 = web[2];
console.log("返回字符串在索引处的字符:", str3); // 输出: 返回字符串在索引处的字符: g

// 字符串转为字符数组
let str4 = [...web];
console.log("字符串转为字符数组:", str4); // 输出: 字符串转为字符数组: [ 'd', 'e', 'n', 'g', 'r', 'u', 'i', 'c', 'o', 'd', 'e', '.', 'c', 'o', 'm' ]

// 字符串转 int
let number = parseInt("168");
console.log("字符串转int:", number); // 输出: 字符串转int: 168

// 字符串替换 (replaceAll 是 ES2021 新增的)
let str6 = web.replaceAll("co", "y");
console.log("替换全部字符串:", str6); // 输出: 替换全部字符串: dengruyide.yom (注意: replaceAll 在旧版浏览器中可能不受支持)

let str7 = web.replace("co", "y");
console.log("替换1个字符串:", str7); // 输出: 替换1个字符串: dengruyide.com (只替换第一个出现的 "co")

// 去除字符串两侧指定的字符 (默认为空白字符)
let str8 = " dengruicode.com ".trim();
console.log("去除字符串两侧指定的字符:", str8); // 输出: 去除字符串两侧指定的字符: dengruicode.com

// 判断是否包含某个字符串
let result = web.includes("dengrui"); // true
console.log("是否包含某个字符串:", result); // 输出: 是否包含某个字符串: true

// 返回字符串中第一次出现某个字符串的位置, 若不存在则返回 -1
let result2 = web.indexOf("dengrui");
console.log("返回字符串中第一次出现某个字符串的位置:", result2); // 输出: 返回字符串中第一次出现某个字符串的位置: 0

let result3 = "www.dengruicode.com".indexOf("dengrui");
console.log("返回字符串中第一次出现某个字符串的位置:", result3); // 输出: 返回字符串中第一次出现某个字符串的位置: 4 (从 "www." 后开始计算)

// 判断一个字符串是否以指定的前缀开头
let result4 = "www.dengruicode.com".startsWith("www");
console.log("判断一个字符串是否以指定的前缀开头:", result4); // 输出: 判断一个字符串是否以指定的前缀开头: true

// 判断一个字符串是否以指定的后缀结尾
let result5 = "www.dengruicode.com".endsWith("net");
console.log("判断一个字符串是否以指定的后缀结尾:", result5); // 输出: 判断一个字符串是否以指定的后缀结尾: false

// 将字符串按照指定字符分割成数组
let arr = "a,b,c,d".split(",");
console.log("将字符串按照指定字符分割成数组:", arr); // 输出: 将字符串按照指定字符分割成数组: [ 'a', 'b', 'c', 'd' ]

// 字符串截取 (substr 方法已被弃用, 建议使用 substring 或 slice)
// 但为了演示, 这里还是使用 substr
let subStr = web.substr(0, 7); // dengrui
console.log("截取字符串的前7个字符:", subStr); // 输出: 截取字符串的前7个字符: dengrui

let subStr2 = web.substr(-3); // com
console.log("截取字符串的最后3个字符:", subStr2); // 输出: 截取字符串的最后3个字符: com (注意: 负数索引从字符串末尾开始计算)

let subStr3 = web.substr(4); // ruicode.com
console.log("从字符串的第5个位置开始截取直至字符串末尾:", subStr3); // 输出: 从字符串的第5个位置开始截取直至字符串末尾: ruicode.com

// 重复字符串
let repeatstr = "David".repeat(3);
console.log("重复3次字符串", repeatstr); // 输出: 重复3次字符串 DavidDavidDavid

// 在字符串前添加指定数量的填充字符, 直到该字符串达到指定的长度
let padStart = "David".padStart(15, "-"); // 由于 David 占 5 个字符, 因此需要再添加 10 个横线, 即可达到总长度 15
console.log("padStart:", padStart); // 输出: padStart: ----------David

// 在字符串后添加指定数量的填充字符, 直到该字符串达到指定的长度
let padEnd = "David".padEnd(10, "-");
console.log("padEnd:", padEnd); // 输出: padEnd: David----- (只添加了 5 个横线, 因为原字符串已经占了 5 个字符)

promise

Promise 是 JavaScript 中用于处理异步操作的一种机制。它代表了一个在未来某个时刻可能会完成或失败的操作,并允许你为这两种情况分别指定处理函数。Promise 提供了更优雅的方式来处理异步操作,避免了传统的回调地狱(callback hell)。

Promise 的三种状态

  1. Pending(待处理):这是 Promise 的初始状态,表示异步操作还未完成。
  2. Fulfilled(已履行):当异步操作成功完成时,Promise 的状态会变为 Fulfilled,此时可以调用 .then() 方法来处理成功的结果。
  3. Rejected(被驳回):当异步操作失败时,Promise 的状态会变为 Rejected,此时可以调用 .catch() 方法来处理错误。

Promise 的基本用法

创建一个 Promise 对象时,你需要传递一个执行器函数(executor function)给 Promise 构造函数。这个执行器函数接受两个参数:resolvereject,它们都是函数。

  • resolve(value):当异步操作成功时,调用此函数,并将操作的结果作为参数传递。这会将 Promise 的状态从 Pending 变为 Fulfilled。
  • reject(reason):当异步操作失败时,调用此函数,并将错误信息作为参数传递。这会将 Promise 的状态从 Pending 变为 Rejected。

Promise 的链式调用

Promise 提供了 .then().catch() 方法来分别处理 Fulfilled 和 Rejected 状态。这两个方法都返回一个新的 Promise,这允许你进行链式调用。

  • .then(onFulfilled, onRejected):当 Promise 状态变为 Fulfilled 时,调用 onFulfilled 函数;当状态变为 Rejected 时,调用 onRejected 函数(可选)。
  • .catch(onRejected):这是 .then(null, onRejected) 的简写形式,专门用于处理错误。

此外,Promise 还提供了 .finally() 方法,无论 Promise 的最终状态如何,都会执行 finally 中的回调函数。这通常用于清理工作,如关闭数据库连接、清除定时器等。

示例代码解析

1
2
3
4
5
6
7
8
9
10
let promise = new Promise((resolve, reject) => {
//resolve("邮件发送成功")
reject("邮件发送失败")
}).then(result => {
console.log("result:", result) // 如果 resolve 被调用,这里会打印结果
}).catch(error => {
console.log("error:", error) // 如果 reject 被调用,这里会打印错误信息
}).finally(() => {
console.log("异步执行结束") // 无论成功还是失败,这里都会执行
});

在这个示例中,我们创建了一个 Promise 对象,并通过调用 reject 函数模拟了一个异步操作的失败。因此,.then() 方法中的回调函数不会被执行,而 .catch() 方法中的回调函数会捕获到错误信息并打印出来。最后,.finally() 方法中的回调函数会执行,打印出“异步执行结束”。

Promise 是处理异步操作的重要工具,它使得代码更加清晰、易于维护。通过合理地使用 Promise,你可以有效地管理复杂的异步流程。

同步与异步编程概念及示例

同步编程

  • 定义:代码按照编写顺序逐行执行,后续的代码必须等待当前正在执行的代码完成之后才能执行。
  • 特点:当遇到耗时的操作时(如网络请求、文件读写等),主线程会被阻塞,直到该操作完成。
  • 示例:就像在单车道路段上发生交通事故导致交通堵塞,只有拖走事故车辆后,后续车辆才能继续行驶。

异步编程

  • 定义:当遇到耗时的操作时,主线程不会被阻塞,而是继续执行后续的代码,等待耗时操作完成后,再通过回调函数或其他机制处理结果。
  • 特点:提高了程序的响应性和性能,因为主线程可以继续执行其他任务。
  • 示例:在具有多车道的高速公路上,发生交通事故后,可以走其他车道继续行驶。

async/await 编程

  • async:当一个函数被标记为async后,该函数会返回一个Promise对象。这允许我们使用await关键字等待异步操作的结果。
  • await:只能在async函数内部使用。加上await关键字后,会在执行到这一行时暂停函数的剩余部分,等待Promise对象解决(即异步操作完成),然后继续执行并获取到异步操作返回的数据。

示例代码

以下是一个HTML文档,其中包含了使用axios库进行网络请求的示例,展示了回调地狱和async/await编程风格的对比。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>异步编程示例</title>

<script src="axios/dist/axios.min.js"></script>

</head>

<body>
<script>



// 回调地狱示例
axios.get('http://127.0.0.1/get')
.then(response => {
console.log("get.data:", response.data);
if (response.data.data.web == "dengruicode.com") {
return axios.get('http://127.0.0.1/article/get/id/1')
.then(response2 => {
console.log("get2.data:", response2.data);
if (response2.data.data.name == "邓瑞") {
return axios.get('http://127.0.0.1/article/get/search/title/入门')
.then(response3 => {
console.log("get3.data:", response3.data);
});
}
});
}
})
.catch(error => {
console.log("get.error:", error);
})
.finally(() => {
console.log("get.finally");
});





// async/await 示例
const getData = async () => {
try {
const response = await axios.get('http://127.0.0.1/get');
console.log("async.get.data:", response.data);
if (response.data.data.web === "dengruicode.com") {
const response2 = await axios.get('http://127.0.0.1/article/get/id/1');
console.log("async.get2.data:", response2.data);
if (response2.data.data.name === "邓瑞") {
const response3 = await axios.get('http://127.0.0.1/article/get/search/title/入门');
console.log("async.get3.data:", response3.data);
}
}
} catch (error) {
console.log("async.get.error:", error);
} finally {
console.log("async.get.finally");
}
};

getData();


</script>

</body>

</html>

在这个示例中,我们首先展示了回调地狱的写法,它使用了多个嵌套的.then()方法来处理连续的异步操作。然后,我们展示了如何使用async/await语法来以同步的方式编写异步代码,从而使代码更加简洁和易读。

Fetch

在现代Web开发中,fetch 是一个非常常用的API,它基于Promise设计,用于发起HTTP请求并接收来自服务器的响应数据。fetch 提供了比传统的 XMLHttpRequest 更简洁和更强大的接口,使得处理HTTP请求变得更加直观和方便。

基本用法

fetch 函数接收一个URL作为参数,并返回一个Promise对象。这个Promise对象会在请求完成时(无论是成功还是失败)被解决。你可以使用 .then() 方法来处理成功的响应,使用 .catch() 方法来处理错误,而 .finally() 方法则会在请求完成后无论结果如何都被执行。

GET 请求示例

在你的代码中,第一个示例展示了如何使用 fetch 发起一个GET请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fetch('http://127.0.0.1/get')
.then(response => {
// 确保响应成功(状态码在200-299之间)
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
// 解析JSON数据
return response.json();
})
.then(data => {
console.log("get.data:", data);
})
.catch(error => {
console.log("get.error:", error.message);
})
.finally(() => {
console.log("get.finally");
});

这里,response.json() 方法用于将响应体解析为JSON对象。注意,在解析JSON之前,最好检查响应是否成功(即状态码是否在200-299之间),以避免在解析错误的响应时抛出异常。

POST 请求示例

对于POST请求,你可以通过传递一个包含请求方法、头部信息和请求体的选项对象来配置 fetch

  1. 发送表单数据

在你的代码中,第二个示例展示了如何发送表单数据(使用 application/x-www-form-urlencoded 编码):

1
2
3
4
5
6
7
8
9
10
11
fetch('http://127.0.0.1/post', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
name: '邓瑞',
web: 'dengruicode.com',
})
})
// ... 后续处理与GET请求相同

这里,URLSearchParams 用于创建查询字符串,它会将对象转换为编码后的URL查询字符串格式。

  1. 发送JSON数据

第三个示例展示了如何发送JSON数据:

1
2
3
4
5
6
7
8
9
10
11
fetch('http://127.0.0.1/postJson', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '邓瑞编程',
web: 'www.dengruicode.com',
})
})
// ... 后续处理与GET请求相同

在这个例子中,JSON.stringify 方法用于将JavaScript对象转换为JSON字符串。注意,当发送JSON数据时,你需要将 Content-Type 头部设置为 application/json

错误处理

.catch() 块中,你可以捕获并处理在请求过程中发生的任何错误,例如网络问题或服务器错误。错误对象通常包含有关错误的详细信息,如错误消息和状态码。

清理工作

.finally() 方法非常有用,因为它会在请求完成后(无论成功还是失败)执行一些清理工作,例如关闭文件、清除计时器等。

总之,fetch API 提供了一种简洁而强大的方式来处理HTTP请求,使得Web开发变得更加高效和愉快。通过结合使用 .then().catch().finally() 方法,你可以轻松地管理请求的生命周期,并处理各种可能的响应和错误情况。

Axios

Axios 概述

Axios 是一个基于 Promise 的网络请求库,设计用于浏览器和 Node.js 环境。它提供了丰富的配置选项,使得发送 HTTP 请求和处理响应变得简单而灵活。Axios 返回一个 Promise 对象,这意味着你可以使用 .then().catch().finally() 方法来处理异步操作的结果。

Fetch 与 Axios 的对比

  1. 环境支持
    • Fetch:主要设计用于浏览器环境,虽然有一些第三方库(如 node-fetch)尝试将其引入 Node.js,但原生的 Fetch API 在 Node.js 中并不可用。
    • Axios:同时支持浏览器和 Node.js 环境,这使得它成为跨平台网络请求的理想选择。
  2. 配置选项
    • Fetch:虽然功能强大,但配置选项相对较少。例如,发送 JSON 数据时,你需要手动设置 Content-Type 头部,并可能需要将对象转换为 JSON 字符串。
    • Axios:提供了更多的配置选项,包括自动转换 JSON 数据、设置请求和响应的拦截器、处理并发请求等。此外,Axios 还允许你轻松地配置默认设置,如基础 URL、超时时间等。
  3. 错误处理
    • Fetch:错误处理相对繁琐。当请求失败时,返回的 Promise 会被拒绝,但你需要检查响应的状态码来确定请求是否真的失败(例如,4xx 和 5xx 状态码)。
    • Axios:错误处理更加直观。当请求失败时,Axios 会抛出一个错误对象,其中包含有关错误的详细信息,如状态码、响应数据和消息。这使得错误处理更加简单和一致。
  4. 拦截器
    • Fetch:不直接支持拦截器功能,但你可以通过封装 fetch 函数来实现类似的功能。
    • Axios:提供了请求和响应的拦截器功能,这使得你可以在请求发送之前或响应到达之前对其进行处理或修改。这对于添加认证令牌、处理全局错误或日志记录等任务非常有用。
  5. 自动转换 JSON
    • Fetch:不会自动将响应数据转换为 JSON 对象。你需要手动调用 response.json() 方法来解析 JSON 数据。
    • Axios:默认情况下会自动将响应数据转换为 JSON 对象(如果服务器返回的是 JSON 格式的数据)。这使得处理 JSON 响应更加简单和直接。
  6. 取消请求
    • Fetch:原生不支持取消请求的功能,但你可以使用 AbortController 来实现这一点(在较新的浏览器中可用)。
    • Axios:提供了内置的取消请求功能,你可以使用 CancelTokenAbortController(在 Axios 的新版本中)来取消正在进行的请求。

Axios 示例代码

在你的示例代码中,展示了如何使用 Axios 发送 GET 和 POST 请求。

  • GET 请求
1
2
3
4
5
6
7
axios.get('http://127.0.0.1/get').then(response => {
console.log("get.data:", response.data);
}).catch(error => {
console.log("get.error:", error);
}).finally(() => {
console.log("get.finally");
});
  • POST 请求(表单数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
axios.get('http://127.0.0.1/get').then(response => {
console.log("get.data:", response.data)
}).catch(error => {
console.log("get.error:", error)
}).finally(() => {
console.log("get.finally")
})

//post请求 post
let data = { //参数
name: '邓瑞',
web: 'dengruicode.com',
}

axios.post('http://127.0.0.1/post', data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(response => {
console.log("post.data:", response.data)
}).catch(error => {
console.log("post.error:", error)
}).finally(() => {
console.log("post.finally")
})

注意,当发送 application/x-www-form-urlencoded 编码的表单数据时,你需要使用 qs 库(或其他类似库)来序列化对象,因为 Axios 默认不会为你做这件事。但在你的示例中,由于未包含 qs 库的序列化步骤,如果服务器期望的是 application/x-www-form-urlencoded 格式的数据,则此请求可能会失败。正确的做法是使用 qs.stringify(data) 来序列化对象,并将其作为 params 传递给 axios.post(如果 Axios 配置为使用 URL 参数发送数据)或作为请求体的一部分,并设置正确的 Content-Type 头部。然而,在你的示例中,你直接将对象作为请求体传递,并设置了 Content-Type 头部为 application/x-www-form-urlencoded,这通常不是发送 JSON 以外数据的正确方式。如果你确实需要发送表单数据,你应该使用类似 URLSearchParams 的东西来序列化数据(但请注意,URLSearchParams 是浏览器内置的,不是 Axios 的)。

  • POST 请求(JSON 数据)
1
2
3
4
5
6
7
axios.post('http://127.0.0.1/postJson', data).then(response => {
console.log("postJson.data:", response.data);
}).catch(error => {
console.log("postJson.error:", error);
}).finally(() => {
console.log("postJson.finally");
});

在这个例子中,Axios 默认会将 data 对象序列化为 JSON 字符串,并设置正确的 Content-Type 头部为 application/json,因此你不需要手动进行这些操作。

总的来说,Axios 提供了比 Fetch 更丰富和灵活的功能,同时保持了简洁和易用的接口。这使得它成为许多开发者的首选网络请求库。

模块化开发概述与importexport详解

模块化开发概念

模块化开发是一种编程实践,旨在将复杂的代码拆分为多个独立的模块。每个模块负责完成特定的功能,从而提高了代码的可读性、可维护性和复用性。

importexport机制

在模块化开发中,export关键字用于将模块内部的代码(变量、函数、类等)导出,以便其他模块能够使用。而import关键字则用于在其他模块中导入这些导出的代码。

分别导出与导入

  • 导出:在模块文件中,可以使用export关键字将多个变量或函数分别导出。
1
2
3
4
5
6
// index.js
let title = "邓瑞编程";
let web = "dengruicode.com";
let getWeb = () => "www.dengruicode.com";

export { title, web, getWeb };
  • 导入:在需要使用这些导出内容的模块中,可以使用import关键字进行导入。同时,可以使用as关键字为导入的变量或函数重命名,以避免命名冲突。
1
2
3
4
5
6
7
8
9
<script type="module">
// 从 index.js 文件中导入 title、web、getWeb 变量/函数,并为 title 重命名为 webTitle
import { title as webTitle, web, getWeb } from './index.js';

console.log(webTitle); // 邓瑞编程
console.log(web); // dengruicode.com
console.log(getWeb()); // www.dengruicode.com
</script>

默认导出与导入

  • 默认导出:在模块文件中,可以使用export default将一个对象、函数或变量作为整体默认导出。
1
2
3
4
5
6
// index.js
let title = "邓瑞编程";
let web = "dengruicode.com";
let getWeb = () => "www.dengruicode.com";

export default { title, web, getWeb };
  • 默认导入:在需要使用默认导出的模块中,可以使用import关键字(不带花括号)进行导入,并为其指定一个名称。
1
2
3
4
5
6
7
8
9
<script type="module">
// 从 index.js 文件中导入默认导出的对象
import obj from "./index.js";

console.log(obj.title); // 邓瑞编程
console.log(obj.web); // dengruicode.com
console.log(obj.getWeb()); // www.dengruicode.com
</script>

使用as关键字进行重命名导入

为了避免命名冲突或提高代码的可读性,可以使用import * as obj语法将整个模块的内容作为一个对象导入,并通过该对象的属性来访问模块中的变量和函数。

1
2
3
4
5
6
7
8
9
<script type="module">
// 从 index.js 文件中导入所有导出的变量/函数,并将它们作为一个对象 obj 的属性
import * as obj from "./index.js";

console.log(obj.title); // 邓瑞编程
console.log(obj.web); // dengruicode.com
console.log(obj.getWeb()); // www.dengruicode.com
</script>

注意事项

  • 在使用模块化开发时,需要确保HTML文件中包含<script type="module">标签,以指示浏览器该脚本应作为ES模块来处理。
  • VSCode扩展“Live Server”可以用于在本地开发环境中预览和运行包含ES模块的HTML文件。但请注意,确保Live Server支持ES模块,并且你的开发环境(如浏览器)也支持ES模块特性。

通过模块化开发,我们可以更好地组织和管理代码,提高代码的可读性和可维护性。同时,importexport机制为我们提供了一种简洁而强大的方式来在不同模块之间共享代码。