# 前端技术栈
# 第 1 章 ES6 新特性
# 1.1 ES6 基本介绍
# 1.1.1 ES6 是什么
(1)ECMAScript 6.0 是 JavaScript 语言的下一代标准
(2)ES6 设计目标:达到 JavaScript 语言可以用来编写复杂的大型程序,成为企业级开发语言
(3)ECMAScript 和 JavaScript 的关系:ECMAScript 是 JavaScript 的规范/规则,JavaScript 是 ECMAScript 的一种实现
# 1.2 let 声明变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>let 的基本使用</title>
<script type="text/javascript">
let name = "hspedu教育";
//console.log("name = ", name) 使用 , 可以输出对象的完整信息
//console.log("name = " + name) 使用 + 表示字符串的拼接,如果 name 是一个对象,会输出 Object,而不会输出对象的完整信息
console.log("name = ", name);
</script>
</head>
<body>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(1)let 声明的变量有严格的局部作用域
(2)let 只能声明一次,var 可以声明多次
(3)let 不存在变量提升,var 存在变量提升
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>let 使用注意事项和细节</title>
<script type="text/javascript">
// let 细节1
//(1) let 在代码块中声明的变量,作用域在代码块中
//(2) var 在代码块中声明的变量,作用域没有限制
{
var name = "韩顺平教育";
let job = "java工程师";
console.log("name = ", name);
console.log("job = ", job);
}
console.log("name = ", name);
//console.log("job = ", job); //报错,job is not defined
//let 细节2
//(1) var 可以声明多次
//(2) let 只能声明一次
var num1 = 100;
var num1 = 200;
console.log(num1);
let num2 = 600;
//let num2 = 500;
console.log(num2); //报错,Uncaught SyntaxError: redeclaration of let num2
//let 细节3
//(1) let 不存在变量提升
//(2) var 存在变量提升
console.log("x = ", x); //undefined
var x = "tom";
console.log("z = ", z); //报错,ReferenceError: can't access lexical declaration 'z' before initialization
let z = "mary";
</script>
</head>
<body>
</body>
</html>
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
# 1.3 const 声明变量/只读变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>const常量/只读变量的使用</title>
<script type="text/javascript">
//const 基本使用
//(1) 常量在定义时,需要赋值
//(2) 常量赋值后不能修改
const PI = 3.14;
console.log("PI = ", PI);
</script>
</head>
<body>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1.4 解构赋值
# 1.4.1 基本介绍
(1)解构赋值是对赋值运算符的扩展
(2)是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值
(3)主要有两种形式:数组解构和对象解构
# 1.4.2 数组解构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数组解构赋值</title>
<script type="text/javascript">
let arr = [1, 2, 3];
//如果要看某个变量的类型
console.log("arr = ", arr);
//数组解构[取出元素]
//1. 传统
let x = arr[0], y = arr[1], z = arr[2];
console.log(x, y, z);
//2. ES6 风格
let [a, b, c] = arr;
console.log("===========");
console.log(a, b, c);
let [num1, num2, num3] = [100, 200, 300];
console.log(num1, num2, num3);
</script>
</head>
<body>
</body>
</html>
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
# 1.4.3 对象解构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象解构</title>
<script type="text/javascript">
//对象解构
/**
* let monster = {name: '牛魔王', age: 800}
* monster 是对象,name、age 是 monster 对象的属性
* */
let monster = {name: '牛魔王', age: 800};
//传统方式取出属性 - 解构 对象名.属性名
console.log(monster.name, " ", monster.age);
//ES6 对象解构
/**
* 细节说明:
* (1) 对象解构时,let{name, age} 中的 name 和 age 名称需要和 monster 对象属性名保持一致
* (2) 也可解构对象部分属性,比如 let{age} 这样就只取出 age 属性
* */
let {name, age} = monster;
console.log("name = ", name, " age = ", age);
//也可以这样写
let {name, age} = {name: '牛魔王', age: 800};
//还有其它的形式,比如方法上使用对象解构
function f1({name, age}) {
console.log("f1-name = ", name, " ", "f1-age = ", age);
}
f1(monster);
</script>
</head>
<body>
</body>
</html>
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
# 1.5 模板字符串
# 1.5.1 基本介绍
(1)模板字符串使用反引号将字符串包裹
(2)可作为普通字符串
(3)可用来定义多行字符串,即可以将换行字符串原生输出
(4)字符串插入变量和表达式,使用 ${}
(5)字符串中调用函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板字符串的使用</title>
<script type="text/javascript">
//1. 字符串,换行会原生输出
let str1 = `for (int i = 0; i < 10; i++){
System.out.println("i = " + i);
}`;
console.log("str1 = ", str1);
//2. 字符串插入变量和表达式,变量名写在 ${} 中,${} 中可以放入 JavaScript 表达式
let name = "hspedu教育";
//当解析 ${name},就找最近的 name 遍历,进行替换
let str2 = `教育名称 = ${name}`;
console.log("str2 = ", str2);
let str3 = `1+2=${1 + 2}`;
console.log("str3 = ", str3);
//3. 字符串中调用函数
function sayHi(name) {
return "hi " + name;
}
let str4 = `sayHi() 返回的结果是 = ${sayHi('jack')}`;
console.log("str4 = ", str4);
</script>
</head>
<body>
</body>
</html>
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
# 1.6 对象相关新特性
# 1.6.1 声明对象简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>声明对象的简写方式</title>
<script type="text/javascript">
const age = 800;
const name = "牛魔王";
//传统方式声明/定义对象
let monster = {name: name, age: age};
//ES6 声明/定义对象
//{name, age} : 表示对象的属性名是 name 和 age
//属性 name 的值和属性 age 的值是从变量/常量里叫 name 的来的
let monster02 = {name, age};
console.log("monster02 = ", monster02);
</script>
</head>
<body>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.6.2 对象方法简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象方法的简写形式</title>
<script type="text/javascript">
//传统方式-对象方法的定义
let monster = {
name: "红孩儿",
age: 100,
sayHi: function () {
console.log("信息: name = ", this.name, " age = ", this.age);
}
}
monster.sayHi();
//ES6-对象方法的定义
let monster2 = {
name: "牛魔王",
age: 900,
sayHi() {
console.log("信息: name = ", this.name, " age = ", this.age);
}
}
monster2.sayHi();
</script>
</head>
<body>
</body>
</html>
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
# 1.6.3 对象拓展运算符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象运算符的扩展</title>
<script type="text/javascript">
let cat = {name: "小花猫", age: 2};
//cat 和 cat2 指向同一个对象空间
/*let cat2 = cat;
cat2.name = "大花猫";
console.log("cat = ", cat); //name = "大花猫", age = 2
console.log("cat2 = ", cat2); //name = "大花猫", age = 2*/
//拷贝对象(深拷贝),此时 cat 和 cat2 指向不同的对象空间
let cat2 = {...cat};
cat2.name = "中花猫";
console.log("cat = ", cat); //小花猫
console.log("cat2 = ", cat2); //中花猫
//合并对象[合并对象时使用的深拷贝,就是改变新的合并的对象的信息时,不会改变旧的对象的信息]
let monster = {name: "白骨精", age: 100};
let car = {brand: "奔驰", price: 800000};
//合并这两个对象
let monster_car = {...monster, ...car};
monster_car.name = "狐狸精";
console.log("monster = ", monster);
console.log("monster_car = ", monster_car);
</script>
</head>
<body>
</body>
</html>
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
# 1.7 箭头函数
# 1.7.1 基本介绍
(1)箭头函数提供更加简洁的函数书写方式
(2)基本语法是:(参数列表) => { 函数体 }
(3)箭头函数没有参数或有多个参数,要用 () 括起来,箭头函数只有一个参数,可以省略 ()
(4)箭头函数函数体有多行语句,用 {} 包裹起来,表示代码块
(5)函数体只有一行语句,并且需要返回结果时,可以省略 {},结果会自动返回
(6)箭头函数多用于匿名函数的定义
# 1.7.2 箭头函数使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数的使用</title>
<script type="text/javascript">
//传统方式定义函数
var f1 = function (n) {
return n * 2;
}
console.log("传统= " + f1(2))
//ES6,箭头函数
let f2 = (n) => {
return n * 2;
}
console.log("f2() 结果 = ", f2(100));
//上面的 ES6 函数的写法,还可以简化
let f3 = n => n * 3;
console.log("f3() 结果 = ", f3(100));
//函数也可以传给一个变量
function hi(f4) {
console.log(f4(900));
}
hi(n => n + 100);
</script>
</head>
<body>
</body>
</html>
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数使用案例2</title>
<script type="text/javascript">
//传统
var f1 = function (n, m) {
var res = 0;
for (var i = n; i <= m; i++) {
res += i;
}
return res;
}
console.log("传统 = " + f1(1, 10));
//ES6 箭头函数使用
let f2 = (n, m) => {
var res = 0;
for (var i = n; i <= m; i++) {
res += i;
}
return res;
};
console.log(f2(1, 10));
</script>
</head>
<body>
</body>
</html>
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
# 1.7.3 箭头函数 + 对象解构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数+对象解构</title>
<script type="text/javascript">
const monster = {
name: "红孩儿",
age: 1000,
skill: ['红缨枪', '三味真火']
}
//要求:在方法形参取出 monster 对象的 skill 属性
//传统方式
function f1(monster) {
console.log("skill = ", monster.skill);
}
f1(monster);
//箭头函数
let f2 = ({skill}) => {
console.log("skill = ", skill);
}
//1. f2 传入对象 monster
//2. f2 形参是 {skill},所以 ES6 的对象解构特性会把 monster 对象的 skill 属性赋给 形参skill
//3. 对象解构的前提就是 {skill} 的 skill 和 monster 的 skill 属性是一致的
f2(monster);
let f3 = ({skill, age, name}) => {
console.log("skill = ", skill, " age = ", age, " name = ", name);
}
f3(monster);
</script>
</head>
<body>
</body>
</html>
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
# 1.8 ES6 课后作业
# 第2章 Promise
# 2.1 Promise 基本介绍
(1)传统的 Ajax 异步调用在需要多个操作的时候会导致多个回调函数嵌套,导致代码不够直观,就是常说的 Callback Hell
(2)为了解决上述问题,Promise 对象应运而生,在 EMCAScript 2015 当中已经成为标准
(3)Promise 是异步编程的一种解决方案
(4)从语法上说,Promise 是一个对象,从它可以获取异步操作的信息
(5)Promise 也是 ES6 的新特性
# 2.2 Promise 应用实例
# 2.2.1 需求分析/图解
# 2.2.2 代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用promise完成多次ajax请求</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//先请求到 monster.json
//1. 创建 Promise 对象
//2. 构造函数传入一个箭头函数
//3. (resolve, reject) 参数列表 resolve:如果请求成功,调用 resolve 函数,如果请求失败,调用 reject 函数
//4. 箭头函数体,仍然是通过 JQuery 发出 ajax
let p = new Promise((resolve, reject) => {
//发出 ajax
$.ajax({
url: "data/monster.json",
success(resultData) {
console.log("promise 发出的第一次 ajax monster 基本信息 = ", resultData);
resolve(resultData);//这里的 resolve 方法把 resultData 参数传递到了下面的 p.then((resultData) 里
},
error(err) {
console.log("promise 发出的第一次 ajax monster 异常 = ", err);
}
})
})
//这里我们可以继续编写第 1 次请求成功后的业务
p.then((resultData) => {
//这里我们可以继续发出请求
$.ajax({
url: `data/monster_detail_${resultData.id}.json`,
success(resultData) { //第 2 次 ajax 请求的回调函数
console.log("第 2 次 ajax 请求 monster 的详细信息 = ", resultData);
},
error(err) {
console.log("promise 发出的异步请求异常 = ", err);
}
})
})
</script>
</head>
<body>
</body>
</html>
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用promise完成多次ajax请求</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//先请求到monster.json
//老韩解读
//1. 创建Promise对象
//2. 构造函数传入一个箭头函数
//3. (resolve, reject) 参数列表resolve: 如果请求成功, 调用resolve函数
//4. 如果请求失败, 调用reject函数
//5. 箭头函数体, 仍然是通过jquery发出ajax
let p = new Promise((resolve, reject) => {
//发出ajax
$.ajax({
url: "data/monster.json",
success(resultData) {//成功的回调函数
console.log("promise发出的第1次ajax monster基本信息=", resultData);
resolve(resultData);
},
error(err) {
//console.log("promise 1发出的异步请求异常=", err);
reject(err);
}
})
})
//这里我们可以继续编写请求成功后的业务
p.then((resultData) => {
//这里我们可以继续发出请求
//console.log("p.then 得到 resultData", resultData);
return new Promise((resolve, reject) => {
$.ajax({
url: `data/monster_detail_${resultData.id}.json`,
success(resultData) { //第2次ajax请求成功,回调函数
console.log("第2次ajax请求 monster的详细信息=", resultData);
//继续进行下一次的请求
resolve(resultData);
},
error(err) { //第2次ajax请求失败,回调函数
//console.log("promise2 发出的异步请求异常=", err);
reject(err);
}
})
})
}).then((resultData) => {
console.log("p.then().then(), resultData", resultData)
//即可以在这里发出第3次ajax请求=》 获取该妖怪的女友
return new Promise((resolve, reject) => {
$.ajax({
url: `data/monster_gf_${resultData.gfid}.json`,
success(resultData) { //第3次ajax请求成功,回调函数
console.log("第3次ajax请求 monster女友的详细信息=", resultData);
//继续进行下一次的请求
//resolve(resultData);
},
error(err) { //第2次ajax请求失败,回调函数
//console.log("promise2 发出的异步请求异常=", err);
//reject(err);
}
})
})
}).catch((err) => { //这里可以对多次ajax请求的异常进行处理
console.log("promise异步请求异常=", err);
})
</script>
</head>
<body>
</body>
</html>
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
# 2.2.3 Promise 代码重排
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise代码重排</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
/**
* 这里我们将重复的代码抽出来编写一个方法 get
* url: ajax 请求的资源路径
* data: ajax 请求携带的数据
* */
function get(url, data) {
return new Promise((resolve, reject) => {
$.ajax({
url: url,
data: data,
success(resultData) {
resolve(resultData);
},
error(err) {
reject(err);
}
})
})
}
//需求:
//1. 先获取 monster.json
//2. 获取 monster_detail_1.json
//3. 获取 monster_gf_2.json
get("data/monster.json")
.then((resultData) => {
//第 1 次 ajax 请求成功后的处理代码
console.log("第 1 次 ajax 请求返回的数据 = ", resultData);
//请求成功后,发第二次请求
return get(`data/monster_detail_${resultData.id}.json`);
}).then((resultData) => {
//第 2 次 ajax 请求成功后的处理代码
console.log("第 2 次 ajax 请求返回的数据 = ", resultData);
return get(`data/monster_gf_${resultData.gfid}.json`);
}).then((resultData) => {
//第 3 次 ajax 请求成功后的处理代码
console.log("第 3 次 ajax 请求返回的数据 = ", resultData);
}).catch((err) => {
console.log("promise请求异常 = ", err);
})
</script>
</head>
<body>
</body>
</html>
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
# 2.3 Promise 课后练习
使用 JQuery-Ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jquery-ajax</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//思路
$.ajax({
url: "data/student_100.json",
success(data) {
console.log("第一次ajax请求数据=", data);
$.ajax({
url: `data/class_${data.class_id}.json`,
success(data) {
console.log("第2次ajax请求数据=", data);
$.ajax({
url: `data/school_${data.school_id}.json`,
success(data) {
console.log("第3次ajax请求数据=", data);
},
error(err) {
console.log("ajax请求发生异常:", err)
}
})
},
error(err) {
console.log("ajax请求发生异常:", err)
}
})
},
error(err) {
console.log("ajax请求发生异常:", err)
}
})
</script>
</head>
<body>
</body>
</html>
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
使用 Promise
promise_utils.js
/**
* 这里我们将重复的代码抽出来编写一个方法 get
* url: ajax 请求的资源路径
* data: ajax 请求携带的数据
* */
function get(url, data) {
return new Promise((resolve, reject) => {
$.ajax({
url: url,
data: data,
success(resultData) {
resolve(resultData);
},
error(err) {
reject(err);
}
})
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise代码重排完成多次ajax请求</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="script/promise_utils.js"></script>
<script type="text/javascript">
get("data/student_100.json").then(data => {
console.log("第 1 次 ajax 请求,返回的数据 = ", data);
return get(`data/class_${data.class_id}.json`);
}).then(data => {
console.log("第 2 次 ajax 请求,返回的数据 = ", data);
return get(`data/school_${data.school_id}.json`);
}).then(data => {
console.log("第 3 次 ajax 请求,返回的数据 = ", data);
}).catch(err => {
console.log("promise异步请求异常 = ", err);
})
</script>
</head>
<body>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 第 3 章 模块化编程
# 3.1 基本介绍
(1)传统非模块化开发有如下的缺点:命名冲突、文件依赖
(2)JavaScript 代码越来越大,JavaScript 引入模块化编程,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块
(3)JavaScript 使用模块的概念来实现模块化编程,解决非模块化编程问题
(4)模块化也是 ES6 的新特性
# 3.2 模块化编程原理示意图
# 3.3 模块化编程分类
(1)CommonJS 模块化规范/ ES5 的写法
(2)ES6 模块化规范
# 3.4 CommonJS 模块编程
# 3.4.1 介绍
(1)每个 js 文件就是一个模块,有自己的作用域,在文件中定义的变量、函数、类/对象都是私有的,对其他 js 文件不可见
(2)CommonJS 使用 module.exports={}
/ exports={}
导出模块,使用 let/const 名称 = require("xx.js")
导入模块
# 3.4.2 代码实现
function.js
//定义对象、变量、常量、函数
const sum = function (a, b) {
return parseInt(a) + parseInt(b);
}
const sub = function (a, b) {
return parseInt(a) - parseInt(b);
}
let name = "韩顺平教育";
const PI = 3.14;
const monster = {
name: "牛魔王",
age: 500,
hi() {
console.log("hi 你好 牛魔王");
}
}
//导出
/**
* (1) module.exports 导出模块
* (2) 把需要导出的数据写入到 {} 中即可
* (3) 可以全部导出,也可以部分导出
* (4) 相当于把导出的数据当做一个对象
* (5) 如果属性名和函数/变量/对象...名字相同,可以简写
* (6) 也可以把 module.exports={} 简写成 exports={}
* */
module.exports = {
sum: sum,
sub: sub,
myname: name
}
/* 简写
module.exports = {
sum,
sub,
name,
PI
}*/
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
use.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>use</title>
<!--在 html 文件中要使用 js 的话-->
<script type="text/javascript" src="./function.js"></script>
</head>
<body>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
use.js
// 当 js 想调用其它 js 的代码
// 导入
/**
* (1) 在 es5 中,我们通过 require 把对应 js 中的数据/对象引入
* (2) 使用的时候通过 m.属性 就可以使用
* (3) 如果我们导入时不需要导入所有的信息,可以导入部分数据
* */
const m = require("./function.js");
//部分导入
const {sub} = require("./function.js");
// 使用
console.log(m.sum("100", "200"));
console.log(m.sub(200, 100));
console.log(m.myname);
console.log(sub(19,8));
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.5 ES6 模块编程
# 3.5.1 介绍
(1)ES6 使用 export {名称/对象/函数/变量/常量}
、export 定义 =
、export default {}
导出模块
(2)使用 import {} from "xx.js"
/ import 名称 from "xx.js"
导入模块
# 3.5.2 批量导出形式
# 3.5.2.1 需求说明
(1)编写 common.js,该文件有函数,变量,常量,对象
(2)要求在 use_common.js 可以使用到 common.js 中定义的 函数/变量/常量/对象
(3)请使用 ES6 模块化编程的方式完成
# 3.5.2.2 思路分析/图解
# 3.5.2.3 代码实现
//定义对象、变量、常量、函数
const sum = function (a, b) {
return parseInt(a) + parseInt(b);
}
const sub = function (a, b) {
return parseInt(a) - parseInt(b);
}
let name = "韩顺平教育";
const PI = 3.14;
const monster = {
name: "牛魔王",
age: 500,
hi() {
console.log("hi 你好 牛魔王");
}
}
//es6 的导出模块/数据
/**
* (1) export 就是导出模块/数据
* (2) 可以全部导出,也可以部分导出
* */
export {
sum,
sub,
name
}
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
//导入
/**
* (1) 可以使用 {} 来接收导出的数据
* (2) 可以全部接收,也可以选择的接收
* (3) 要求导入的名称和导出的名称一致
* */
import {sub, sum, name} from "./common";
//使用
console.log(sum(10,90));
console.log(name);
2
3
4
5
6
7
8
9
10
11
12
# 3.5.3 其它导出形式
(1)
//定义对象、变量、常量、函数
//定义 sum 函数时,就直接导出
export const sum = function (a, b) {
return parseInt(a) + parseInt(b);
}
const sub = function (a, b) {
return parseInt(a) - parseInt(b);
}
let name = "韩顺平教育";
const PI = 3.14;
const monster = {
name: "牛魔王",
age: 500,
hi() {
console.log("hi 你好 牛魔王");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//可以导入模块/数据
import {sum} from "./common2";
console.log(sum(10, 30));
2
3
4
(2)默认导出
//定义对象、变量、常量、函数
//默认导出
export default {
sum(a, b) {
return parseInt(a) + parseInt(b);
},
sub(a, b) {
return parseInt(a) - parseInt(b);
}
}
2
3
4
5
6
7
8
9
10
11
12
//导入默认导出的模块/数据
import m from "./common3";
console.log(m.sub(80, 90));
2
3
4
# 3.5.4 注意事项和使用细节
(1)ES6 的模块化无法在 Node.js 中执行,需要用 Babel 转码 ES5 后再执行
(2)export 不仅可以导出对象,一切 JS 变量都可以导出,比如:基本类型变量、函数、数组、对象
(3)没有导出的不能使用
(4)ES6 的导出方式较多,不同的导出方式对导入方式也有一定影响
# 3.6 模块化编程作业
# 第 4 章 Vue
# 4.1 Vue 基本介绍
(1)Vue 是一个前端框架,易于构建用户界面
(2)Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或项目整合
(3)支持和其它类库结合使用
(4)开发复杂的单页应用非常方便
(5)Vue 是 Vue.js 的简称
# 4.2 MVVM
(1)M:即 Model 模型,包括数据和一些基本操作
(2)V:即 View 视图,页面渲染结果
(3)VM:即 View-Model,模型与视图间的双向操作
(4)在 MVVM 之前,开发人员从后端获取需要的数据模型,然后要通过 DOM 操作 Model 渲染到 View 中,而后当用户操作视图时我们还需要通过 DOM 获取 View 中的数据,然后同步到 Model 中。
(5)而 MVVM 中的 VM 要做的事情就是把 DOM 操作完全封装起来,开发人员不用再关心 Model 和 View 之间是如何相互影响的
(6)只要我们 Model 发生了改变,View 上自然就会表现出来
(7)当用户修改了 View,Model 中的数据也会跟着改变
(8)把开发人员从繁琐的 DOM 操作中解放出来,把关注点放在如何操作 Model 上,大大提高开发效率
# 4.3 快速入门
# 4.3.1 需求说明/图解
(1)使用 vue 完成显示
# 4.3.2 代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue快速入门</title>
</head>
<body>
<div id="app">
<!--
1. {{message}} : 插值表达式
2. message 就是从 model 的 data 数据池来设置
3. 当我们的代码执行时,会到 data{} 数据池中去匹配数据,如果匹配上就进行替换,如果没有匹配上就输出空
-->
<h1>欢迎你{{message}}-{{name}}</h1>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
message: "Hello-Vue!",
name: "韩顺平教育"
}
})
</script>
</body>
</html>
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
# 4.3.3 Vue 数据绑定机制分析
(1)通过查看浏览器的控制台,可以分析 Vue 数据绑定机制/ MVVM
# 4.3.4 注意事项和使用细节
(1)注意代码顺序,要求 div 在前,script 在后,否则无法绑定数据
(2)从案例可以体会声明式渲染:Vue.js 采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统,做到数据和显示分离
(3)Vue 没有繁琐的 DOM 操作,如果使用 JQuery,我们需要先找到 div 节点,获取到 DOM 对象,然后进行节点操作,显然 Vue 更加简洁
# 4.4 数据单向渲染
# 4.4.1 基本说明
(1)v-bind
指令可以完成基本数据渲染/绑定
(2)v-bind
简写形式就是一个冒号 (😃
# 4.4.2 应用实例
# 4.4.2.1 需求分析/图解
(1)演示 v-bind
的使用,可以绑定元素的属性
# 4.4.2.2 代码实现
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>单向数据渲染</title>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<!--
(1) 使用插值表达式引用 data 数据池数据是在标签体内
(2) 如果是在标签/元素的属性上去引用 data 数据池数据时不能使用插值表达式,而是需要使用 v-bind
-->
<img v-bind:src="img_src" v-bind:width="img_width">
<!--简写-->
<img :src="img_src" :width="img_width">
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
message: "Hello, 耗子精",
img_src: "1.jpg",
img_width: "200px",
}
})
</script>
</body>
</html>
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
# 4.4.3 注意事项和使用细节
(1)插值表达式是用在标签体的
(2)如果给标签属性绑定值,则使用 v-bind 指令
# 4.5 数据双向绑定
# 4.5.1 基本说明
v-model
可以完成双向数据绑定
# 4.5.2 应用实例
(1)在输入框中输入信息,会更新到相应绑定的位置
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>双向数据渲染</title>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<!--
(1) v-bind 是数据单向渲染,data 数据池绑定的数据发生变化会影响 view
(2) v-model="" 是数据的双向渲染,data 数据池绑定的数据发生变化会影响 view
view 关联的元素的值发生变化会影响 data 数据池的值的变化
-->
<input type="text" v-model="hobby.val"><br/><br/>
<input type="text" v-bind:value="hobby.val"><br/><br/>
<p>你输入的爱好是: {{hobby.val}}</p>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
message: "Hi,输入你的爱好",
hobby: {
val: "购物",
}
}
})
</script>
</body>
</html>
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
# 4.5.3 课后练习
需求:使用 Vue 的数据双向绑定完成如下功能
(1)当用户在数据框输入 1.jpg、2.jpg、3.jpg 时可以切换显示对应的图片
(2)使用 Vue 的数据双向绑定完成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>请输入图片名称 1.jpg-2.jpg-3.jpg</h1>
<input type="text" v-model="img_src"><br/><br/>
<img :src="img_src" :height="img_height"><br/>
<img src="1.jpg" :height="img_height"><br/>
<img src="2.jpg" :height="img_height"><br/>
<img src="3.jpg" :height="img_height"><br/>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
img_src: "1.jpg",
img_height: "150px",
}
})
</script>
</body>
</html>
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
# 4.6 事件绑定
# 4.6.1 基本说明
(1)使用 v-on
进行事件处理,比如:v-on:click
表示处理鼠标点击事件
(2)事件调用的方法定义在 vue 对象声明的 methods 节点中
(3)v-on:事件名
可以绑定指定事件
# 4.6.2 应用实例
需求:演示 Vue 事件绑定操作
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>事件处理</title>
</head>
<body>
<!--视图-->
<div id="app">
<h1>{{message}}</h1>
<!--
(1) v-on:click 表示我们要给 button 元素绑定一个 click 的事件
(2) sayHi() 表示绑定的方法,是在方法池 methods{} 中定义的
-->
<button v-on:click="sayHi()">点击输出</button>
<button v-on:click="sayOk()">点击输出</button>
<button>点击输出</button>
<button>点击输出</button>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
message: "Vue事件处理的案例",
},
//methods: {} 是一个 methods 属性,对应的值是对象 {}
//在 {} 中,可以写很多的方法,可以理解是一个方法池
methods: {
sayHi() {
console.log("hi, 银角大王");
},
sayOk() {
console.log("ok, 金角大王");
},
}
})
</script>
</body>
</html>
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
# 4.6.3 注意事项和使用细节
(1)如果方法没有参数,可以省略()
(2)v-on:
指令的简写形式是 @
# 4.6.4 课后作业
需求1:如图点击按钮,次数联动变化
(1)当用户点击增加+1按钮时,次数+1
(2)当用户点击增加+2按钮时,次数+2
(3)使用常规方法和表达式完成
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>事件处理-作业1</title>
</head>
<body>
<!--视图-->
<div id="app">
<h1>{{message}}</h1>
<button v-on:click="add">点击增加+1</button>
<!--<button v-on:click="add2">点击增加+2</button>-->
<!--
当调用的方法里只有一条语句的时候可以直接将语句写在方法名的位置
这里 count += 2 的 count 数据是 data 数据池的 count
-->
<button v-on:click="count += 2">点击增加+2</button>
<p>你的按钮被点击了{{count}}次</p>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
message: "Vue事件处理的作业",
count: 0, //点击的次数
},
//methods: {} 是一个 methods 属性,对应的值是对象 {}
//在 {} 中,可以写很多的方法,可以理解是一个方法池
methods: {
add() {
//修改 data 数据池的 count
//因为 data 和 methods 在同一个 vue 实例中,因此可以通过 this 获得数据
this.count += 1;
},
/*add2() {
//修改 data 数据池的 count
//因为 data 和 methods 在同一个 vue 实例中,因此可以通过 this 获得数据
this.count += 2;
}*/
}
})
</script>
</body>
</html>
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
需求2:如图,根据用户的输入,弹窗显示内容
(1)用户可以在输入框输入内容
(2)点击按钮可以显示书名
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>事件处理-作业2</title>
</head>
<body>
<!--视图-->
<div id="app">
<h1>{{message}}</h1>
请输入书名: <input type="text" v-model="bookName">
<button v-on:click="show()">点击显示书名~</button>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //data{} 表示数据池,有很多数据,以 K-V 的形式设置(根据业务需要来设置)
message: "Vue事件处理的作业",
bookName: "天龙八部"
},
//methods: {} 是一个 methods 属性,对应的值是对象 {}
//在 {} 中,可以写很多的方法,可以理解是一个方法池
methods: {
show() {
alert("你输入的书名是: " + this.bookName)
}
}
})
</script>
</body>
</html>
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
# 4.7 修饰符
# 4.7.1 基本说明
(1)修饰符(Modifiers)是以(.)指明的后缀,指出某个指令以特殊的方式绑定
# 4.7.2 应用实例
# 4.7.2.1 需求分析
演示 v-on:submit.prevent
的使用,如果没有输入名字,控制台输出“请输入名字”,否则输出“提交表单”
那么为什么在开发中有时需要让某个指令以特殊的方式绑定,比如表单提交?
(1)我们不希望将这个表单进行整体提交而是以 Ajax 的方式进行提交
(2)因为表单整体提交会导致重载页面,而 Ajax 方式可以有选择性的提交数据,并且局部刷新
# 4.7.2.2 代码实现
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Vue修饰符的使用</title>
</head>
<body>
<div id="app">
<!--
(1) 修饰符用于指出一个指令应该以特殊方式绑定
(2) v-on:submit.prevent 的 .prevent 修饰符表示阻止表单提交的默认行为
(3) v-on:submit.prevent="onMySubmit" 表示提交按钮就不执行默认的提交操作,而是执行 onMySubmit 方法
-->
<form action="http://www.baidu.com" v-on:submit.prevent="onMySubmit">
妖怪名: <input type="text" v-model="monster.name"><br/><br/>
<button type="submit">注册</button>
</form>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //数据池
monster: { //monster 数据(对象)的属性可以动态生成,即通过标签的双向绑定机制
}
},
methods: {
onMySubmit() {
if (this.monster.name) { //不为空
console.log("提交表单 name = ", this.monster.name);
//这里,程序员就可以根据自己的业务发出 ajax 请求到后端
//得到数据后再进行数据更新
} else { //为空
console.log("请输入名字");
}
}
}
})
</script>
</body>
</html>
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
# 4.8 条件渲染/控制:v-if v-show
# 4.8.1 基本说明
(1)JavaScript 中 null、undefined、""(空串)
都认为是 false
(2)Vue 提供了 v-if
和 v-show
条件指令完成条件渲染/控制
(3)判断的流程:比如有 v-if="awesome"
那么程序会到 data 数据池中找到 awesome 的属性值是什么,如果是 false 则判断结果就是 false
# 4.8.2 应用实例
# 4.8.2.1 需求分析
需求:演示条件渲染使用(使用 v-if 和 v-show 实现)
、
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-if</title>
</head>
<body>
<div id="app">
<!--checkbox 勾选上时 value 值是 true,没有勾选上时 value 值是 false-->
<input type="checkbox" v-model="sel">是否同意条款[v-if实现]
<h1 v-if="sel">你同意条款</h1>
<h1 v-else>你不同意条款</h1>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //数据池
sel: false,
},
})
</script>
</body>
</html>
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-show</title>
</head>
<body>
<div id="app">
<!--checkbox 勾选上时 value 值是 true,没有勾选上时 value 值是 false-->
<input type="checkbox" v-model="sel">是否同意条款[v-show实现]
<h1 v-show="sel">你同意条款</h1>
<h1 v-show="!sel">你不同意条款</h1>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //数据池
sel: false,
},
})
</script>
</body>
</html>
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
# 4.8.3 v-if
和 v-show
(1)v-if
会确保在切换过程中,条件块内的事件监听器和子组件销毁和重建
(2)v-show
机制相对简单,不管初始条件是什么,元素总是会被渲染,并且只是对 CSS 进行切换
(3)使用建议:如果要频繁地切换,建议使用 v-show
;如果运行时条件很少改变,使用 v-if
较好
# 4.8.4 课后作业
需求:如图,当用户输入成绩时,可以输出对应的级别
(1)90 分以上,显示优秀
(2)70 分以上,显示良好
(3)60 分以上,显示及格
(4)低于 60 分,显示不及格
(5)如果用户输入的成绩大于 100,就修正成 100,如果用户输入的成绩小于 0,就修正成 0
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>条件渲染的作业</title>
</head>
<body>
<div id="app">
<h1>演示条件判断</h1>
请输入成绩 1-100 <input type="text" v-model="score" v-on:blur="setScore">
<!--如果用户输入的成绩大于 100,就修正成 100,如果用户输入的成绩小于 0,就修正成 0-->
<!-- 思路
(1) 当用户输入成绩后,判断成绩的范围并进行修正
(2) 事件处理: onblur[失去焦点事件]
-->
<p>你输入的成绩是:{{score}}</p>
<div v-if="score >= 90">你的成绩优秀</div>
<div v-else-if="score >= 70">你的成绩良好</div>
<div v-else-if="score >= 60">你的成绩及格</div>
<div v-else="score < 60">你的成绩不及格</div>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //数据池
score: 0,
},
methods: {
setScore() {
//判断分数并修正
if (this.score > 100) {
this.score = 100;
}
if (this.score < 0) {
this.score = 0;
}
}
}
})
</script>
</body>
</html>
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
# 4.9 列表渲染:v-for
# 4.9.1 基本说明
(1)Vue 提供了 v-for
列表循环指令
(2)对数组进行遍历
(3)用 v-for
来遍历一个对象的 property
# 4.9.2 应用实例
# 4.9.2.1 需求分析
需求:演示列表渲染使用(v-for)
# 4.9.2.2 代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-for</title>
</head>
<body>
<div id="app">
<h1>简单的列表渲染</h1>
<!--基本语法: <li v-for="变量 in 数字">{{ 变量 }}</li>-->
<ul>
<li v-for="i in 3">{{i}}</li>
</ul>
<h1>简单的列表渲染-带索引</h1>
<!--基本语法:<li v-for="(变量, 索引) in 值">{{ 变量 }} - {{ 索引 }}</li>-->
<ul>
<li v-for="(i, index) in 3">{{i}} - {{index}}</li>
</ul>
<h1>遍历数据列表</h1>
<!--基本语法:
<tr v-for="对象 in 对象数组">
<td>{{对象的属性}}</td>
</tr>
-->
<table width="400px" border="1px">
<tr v-for="monster in monsters">
<td>{{monster.id}}</td>
<td>{{monster.name}}</td>
<td>{{monster.age}}</td>
</tr>
</table>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //数据池
monsters: [
{id: 1, name: '牛魔王', age: 800},
{id: 2, name: '黑山老妖', age: 900},
{id: 3, name: '红孩儿', age: 200}
]
},
})
</script>
</body>
</html>
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
# 4.9.3 课后练习
需求:如图,显示成绩及格的学生列表
(1)将学生对象存放到数组中
(2)遍历显示所有学生,只显示成绩及格的学员
# 4.10 组件化编程
# 4.10.1 基本说明
(1)在大型应用开发的时候,页面可以划分成很多部分,往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航
(2)但是如果每个页面都独自开发,这无疑增加了我们开发的成本,所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发
(3)组件是一个 Vue 实例,也包括:data、methods、生命周期函数等
(4)组件渲染需要 Html 模板,所以增加了 template 属性,值就是 Html 模板
(5)对于全局组件,任何 Vue 实例都可以直接在 Html 中通过组件名称来使用组件
(6)data 是一个函数,不再是一个对象,这样每次引用组件都是独立的对象
# 4.10.2 应用实例
# 4.10.2.1 为什么需要组件化编程
需求:点击一个按钮,可以显示点击的次数
# 4.10.2.2 实现方式1 - 普通方式
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>组件化编程1</title>
</head>
<body>
<div id="app">
<!--非组件化方式-普通方式-->
<button v-on:click="click1()">点击次数= {{count}} 次 【非组件化方式】</button> <br/><br/>
<!--需求是如果有多个按钮,都要进行点击统计的话
(1) 其实三个按钮界面其实一样,但是目前我们都重新写了一次,复用性低
(2) 点击各个按钮的业务都是对次数 +1,因此业务处理类似,但是也都是重新写了一个方法,复用性低
(3) 解决办法:组件化编程
-->
<button v-on:click="click2()">点击次数= {{count2}} 次 【非组件化方式】</button> <br/><br/>
<button v-on:click="click3()">点击次数= {{count3}} 次 【非组件化方式】</button>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
data: { //数据池
count: 10,
count2: 10,
count3: 10
},
methods: {
click1() {
this.count++;
},
click2() {
this.count2++;
},
click3() {
this.count3++;
},
}
})
</script>
</body>
</html>
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
# 4.10.2.3 实现方式2 - 全局组件方式
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>组件化编程2</title>
</head>
<body>
<div id="app">
<h1>组件化编程-全局组件</h1>
<!--使用全局组件
这样使用 Vue 会把 <counter></counter> 替换成下面 template 的模板内容
-->
<counter></counter> <br/><br/>
<counter></counter>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//(1) 定义一个全局组件,名称为 counter(自己定)
//(2) {} 表示的就是我们的组件的相关的内容
//(3) template 指定该组件的界面,因为会引用到数据池的数据,所以需要使用模板字符串
//(4) 重点:要把组件视为一个 Vue 实例,也有自己的数据池和方法池
//(5) 对于组件,我们的数据池的数据是使用函数返回[目的是为了保证每个组件的数据是独立的],所以不能使用原来的方式
Vue.component("counter", {
template: `<button v-on:click="click()">点击次数= {{count}} 次 【全局组件化方式】</button>`,
data() { //注意:和原来的方式不一样
return {
count: 10
}
},
methods: {
click() {
this.count++;
}
}
})
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
})
</script>
</body>
</html>
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
# 4.10.2.4 实现方式3 - 局部组件方式
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>组件化编程2</title>
</head>
<body>
<div id="app">
<h1>组件化编程-局部组件</h1>
<!--使用局部组件,该组件是从挂载到 app 的 vue 中得到的-->
<my_counter></my_counter> <br/>
<my_counter></my_counter> <br/>
<my_counter></my_counter> <br/>
</div>
<!--引入 vue.js-->
<script src="vue.js"></script>
<script>
//定义一个组件,组件名称为 buttonCounter
/**
* (1) 可以把常用的组件定义在某个 commons.js 中,然后用 export 导出供其他页面使用
* (2) 如果某个页面需要使用直接用 import 导入
* */
const buttonCounter = {
template: `<button v-on:click="click()">点击次数= {{count}} 次 【局部组件化方式】</button>`,
data() { //注意:和原来的方式不一样
return {
count: 10
}
},
methods: {
click() {
this.count++;
}
}
}
//创建 Vue 对象
let vm = new Vue({
el: "#app", //创建的 vue 实例挂载到 id = app 的 div
components: { //引入某个组件
'my_counter': buttonCounter //此时 my_counter 就是一个组件,是一个局部组件,它的使用范围在当前的 Vue
}
})
</script>
</body>
</html>
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
# 4.10.2.5 注意事项和细节说明
(1)全局组件是属于所有 Vue 实例,因此可以在所有的 Vue 的实例中使用
(2)组件定义需要放置在 new Vue()
前,否则组件注册会失败
(3)组件也是一个 Vue 实例,因此它的定义也存在:data、methods、生命周期函数等
(4)data 是一个函数,不再是一个对象,这样每次引用组件都是独立的对象
(5)组件渲染需要 Html 模板,所以增加了 template 属性,值就是 Html 模板
# 4.11 生命周期和监听函数(钩子函数)
# 4.11.1 基本说明
(1)Vue 实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂载 DOM、渲染-更新-渲染、卸载等一系列过程,我们称为 Vue 实例的生命周期
(2)钩子函数(监听函数):Vue 实例在完整的生命周期过程中(比如设置数据监听、编译模板、将实例挂载到 DOM、在数据变化时更新 DOM 等),也会运行叫做生命周期钩子的函数
(3)钩子函数的作用就是在某个阶段,给程序员一个做某些处理的机会
# 4.11.2 图解
(1)new Vue()
:new 了一个 Vue 的实例对象,此时就会进入组件的创建过程
(2)Init Events & Lifecycle
:初始化组件的事件和生命周期函数
(3)beforeCreate
:组件创建之后遇到的第一个生命周期函数,这个阶段 data 和 methods 以及 dom 结构都未被初始化,也就是获取不到 data 的值,不能调用 methods 中的函数
(4)Init injections & reactivity
:这个阶段中,正在初始化 data 和 methods 中的方法
(5)created
:这个阶段组件的 data 和 methods 中的方法已初始化结束,可以访问,但是 dom 结构未初始化,页面未渲染,在这个阶段经常会发起 Ajax 请求
(6)编译模板结构(在内存)
(7)beforeMount
:当模板在内存中编译完成,此时内存中的模板结构还未渲染到页面上,看不到真实的数据
(8)Create vm.$el and replace 'el' with it
:这一步再把内存中渲染好的模板结构替换至真实的 dom 结构
(9)mounted
:此时,页面渲染好,用户看到的是真实的页面数据,生命周期创建阶段完毕,进入到了运行中的阶段
(10)生命周期运行中:
1)beforeUpdate
:当执行此函数,数据池的数据是新的,但是页面是旧的
2)Virtual DOM re-render and patch
:根据最新的 data 数据,重新渲染内存中的模板结构,并把渲染好的模板结构替换至页面上
3)updated
:页面已经完成了更新,此时,data 数据和页面的数据都是新的
(11)beforeDestroy
:当执行此函数时,组件即将被销毁,但是还没有真正开始销毁,此时组件 data、methods 数据或方法还可以被调用
(12)Teardown......
:注销组件和事件监听
(13)destroyed
:组件已经完成了销毁
# 4.11.3 应用实例 - 展示 Vue 实例的生命周期和钩子函数的执行时机
# 4.11.3.1 需求分析
需求:展示 Vue 实例的生命周期和钩子函数的执行时机
(1)重点研究几个重要的钩子函数
(2)在这几个钩子函数中,数据模型是否加载/使用?自定义方法是否加载/可用?Html 模板是否加载/使用?Html 模板是否完成渲染?
# 4.11.3.2 代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue生命周期和钩子函数</title>
</head>
<body>
<!--这里可以视为用户看到的页面 - 对应前面讲解的页面 dom-->
<div id="app">
<span id="num">{{num}}</span>
<button @click="num++">赞!</button>
<h2>{{name}}, 有 {{num}} 次点赞</h2>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: { //数据池
name: "kristina",
num: 0
},
methods: {
show() {
return this.name;
},
add() {
this.num++;
}
},
beforeCreate() { //生命周期函数 - 创建 Vue 实例前
console.log("======beforeCreate======");
console.log("数据模型/数据池的数据是否加载/使用? [没有加载]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用? [没有加载]", this.show());
console.log("用户页面(Html页面) dom 是否加载/使用? [以加载]", document.getElementById("num"));
console.log("用户页面(Html页面) dom 是否被渲染? [没有渲染]", document.getElementById("num").innerText);
},
created() { //生命周期函数 - 创建 vue 实例
console.log("======created======");
console.log("数据模型/数据池的数据是否加载/使用? [已加载]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用? [已加载]", this.show());
console.log("用户页面(Html页面) dom 是否加载/使用? [以加载]", document.getElementById("num"));
console.log("用户页面(Html页面) dom 是否被渲染? [没有渲染]", document.getElementById("num").innerText);
//可以发出 Ajax
//接收返回的数据,再次去更新 data 数据池的数据
//编译内存模板结构
},
beforeMount() { //生命周期函数 - 挂载前
console.log("======beforeMount======");
console.log("数据模型/数据池的数据是否加载/使用? [已加载]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用? [已加载]", this.show());
console.log("用户页面(Html页面) dom 是否加载/使用? [已加载]", document.getElementById("num"));
console.log("用户页面(Html页面) dom 是否被渲染? [没有渲染]", document.getElementById("num").innerText);
},
mounted() { //生命周期函数 - 挂载后
console.log("======mounted======");
console.log("数据模型/数据池的数据是否加载/使用? [已加载]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用? [已加载]", this.show());
console.log("用户页面(Html页面) dom 是否加载/使用? [已加载]", document.getElementById("num"));
console.log("用户页面(Html页面) dom 是否被渲染? [已渲染]", document.getElementById("num").innerText);
},
beforeUpdate() { //生命周期函数 - 数据池数据更新前
console.log("======beforeUpdate======");
console.log("数据模型/数据池的数据是否加载/使用? [已加载]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用? [已加载]", this.show());
console.log("用户页面(Html页面) dom 是否加载/使用? [已加载]", document.getElementById("num"));
console.log("用户页面(Html页面) dom 数据是否被更新? [未更新]", document.getElementById("num").innerText);
},
updated() { //生命周期函数 - 数据池数据更新后
console.log("======beforeUpdate======");
console.log("数据模型/数据池的数据是否加载/使用? [已加载]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用? [已加载]", this.show());
console.log("用户页面(Html页面) dom 是否加载/使用? [已加载]", document.getElementById("num"));
console.log("用户页面(Html页面) dom 数据是否被更新? [已更新]", document.getElementById("num").innerText);
}
})
</script>
</body>
</html>
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
# 4.11.4 小结
Vue 实例生命周期是非常重要的,Vue 编程模型都是建立在此基础上
# 4.11.5 作业
(1)简述 Vue 实例的生命周期流程
(2)beforeUpdate 和 updated 在什么时候被调用
(3)在 Vue 页面,如果要从后端获取到商品列表,在什么时机发出合适,为什么?
(4)手绘 Vue 实例的生命周期流程
# 4.12 Vue2 脚手架模块化开发
# 4.12.1 需求分析
为什么需要 Vue Cli 脚手架?
目前开发模式的问题?
(1)开发效率低
(2)不够规范
(3)维护和升级,可读性比较差
需求:使用 Vue 脚手架进行模块化开发,输入不同的 url,切换不同页面
# 4.12.2 环境配置 - 搭建项目
# 4.12.3 IDEA打开项目,运行项目
(1)将 Vue 脚手架项目直接拖到 IDEA,就可以直接打开
(2)配置 npm
# 4.12.4 课后练习
# 4.12.5 Vue 项目结构分析
# 4.12.6 Vue 请求页面执行流程
当输入 http://localhost:8080
时,页面是怎么来的,这里涉及到如下文件
# 4.12.7 Vue 项目简写造成理解困难,测试梳理疑惑
(1)因为 Vue 默认生成的项目代码使用了很多简写,造成理解困难
(2)整个页面渲染过程中,main.js 是中心,也是连接各个组件、路由器的关键,这里分析一下 main.js
# 4.12.8 路由切换
(1)根据 Vue 请求执行的流程,完成路由切换实例
(2)浏览器输入 http://localhost:8080/#/hello 看到这个页面
浏览器输入 http://localhost:8080/#/ 看到这个页面
# 4.12.9 ElementUI 的使用
# 第 5 章 Axios
# 5.1 基本说明
(1)Axios 是独立于 Vue 的一个项目,不是 Vue 的一部分
(2)Axios 通常和 Vue 一起使用,实现 Ajax 操作
(3)Axios 是一个基于 Promise 的 Http 库
# 5.2 Axios 库文件
(1)使用 Axios 需要引入 Axios 库文件
(2)可以直接引入,也可以下载 Axios.min.js 后在本地引入
# 5.3 Axios 应用实例
需求:在 Vue 项目中使用 Axios,从服务器获取 json 数据,显示在页面
data/response.data.json
{
"success": true,
"message": "成功",
"data": {
"items": [
{
"name": "牛魔王",
"age": 800
},
{
"name": "红孩儿",
"age": 500
},
{
"name": "蜈蚣精",
"age": 200
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
axios_quick_start.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>axios的应用实例</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<table border="1" width="200">
<tr>
<td>名字</td>
<td>年龄</td>
</tr>
<tr v-for="monster in monsterList">
<td>{{monster.name}}</td>
<td>{{monster.age}}</td>
</tr>
</table>
</div>
<script src="vue.js"></script>
<script src="axios.min.js"></script>
<script>
new Vue({
el: "#app",
data: {
msg: "妖怪信息列表",
monsterList: [] //表示妖怪的信息数组
},
methods: { //定义方法
list() { //发出 ajax 请求,获取数据
/*
* (1) axios.get() 表示发出 ajax 请求
* (2) "http://localhost:63342/axios/data/response.data.json" 表示请求的 url
* (3) axios 发出 ajax 请求的基本语法:axios.get(url).then(箭头函数).then(箭头函数)...catch(箭头函数)
* (4) 如果 get 请求成功进入到第一个 then(),可以在第一个 then() 中继续发出 axios 的 ajax 请求,return axios.get(url),如果有异常,会进入到 catch(箭头函数)
* (5) list 方法在 Vue 的生命周期函数 created() 中调用
* */
axios.get("http://localhost:63342/axios/data/response.data.json")
.then((responseData) => {
console.log("responseData.data.data.item", responseData.data.data.items)
//将妖怪列表数组信息,绑定到 data 数据池的 monsterList
this.monsterList = responseData.data.data.items;
//可以再次发出 ajax 请求
//return axios.get(url)
}).catch(err => {
console.log("异常 = ", err)
})
}
},
created() {
this.list();
}
})
</script>
</body>
</html>
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