08-非单文件组件VC
码路教育 6/3/2022
# 1, 组件化开发
Vue特点: 组件化、声明式编程、虚拟DO+DIFF
- 组件:component
# 1.1, 什么是组件化开发
组件化开发思想
- 将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展;
- 但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了
- 如果我们将一个个功能块拆分后,就可以像搭建积木一下来搭建我们的项目
- 现在整个的大前端开发都是组件化的天下
- 无论从三大框架(Vue、React、Angular),还是跨平台方案的Flutter,甚至是移动端都在转向组件化开发,包括小程序的开发也是采用组件化开发的思想
- 组件: 复用的【代码 + 资源(图片、样式、视频)】集合在一起即为组件
以组件化的思想考虑整个项目
- 将一个完整的页面分成很多个组件
- 每个组件都用于实现页面的一个功能块
- 而每一个组件又可以进行细分
- 而组件本身又可以在多个地方进行复用
- 组件化提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用
- 任何的应用都会被抽象成一颗组件树
# 1.2, 组件的基本的使用
Vue框架中从书写角度出发:分为两大类组件
- 单文件组件: 一个文件即为一个组件, 这个文件的尾缀务必是.vue,目前我们不会学习
- 非单文件组件: 一个文件里面,可以定义多个组件,这个文件尾缀.html.
非单文组件使用分为三步骤
- 第一步: 定义
- 定义一个组件:利用的是Vue.extend方法去定义组件
- extend方法里面也需要传递配置对象,extend配置对象与Vue配置对象几乎一模一样!!!
- 第二步: 注册
- 注册,某一个地方需要组件,进行注册。在components配置项进行注册
- 第三步: 使用
- 使用,【是以自定义标签的形式使用,首字母一般大写】
注意点
- 不能书写el、组件的响应式数据务必比是函数写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!--
vue的特点:
1)组件化开发 component
2)声明式编程
3)虚拟DOM+DIFF
-->
<!-- 定义的容器 -->
<div id="app">
<Hello></Hello>
<Hello></Hello>
<Hello></Hello>
<Hello></Hello>
<Hello></Hello>
</div>
<script>
// 在extend中传组件的配置项
// 之前new Vue时,传递的配置项,在Vuex.extend中基本上都可以配置
let Hello = Vue.extend({
// el 只有要根组件中才可以配置el,在普通组件中不能配置el
template:"<h2>我是Hello组件</h2>", // 配置当前组件对应的模板
})
// 注册组件分两类:
// 1)全局注册 先不讲
// 2)局部注册
let vm = new Vue({
el:"#app",
data(){
return {
}
},
components:{
Hello
}
});
</script>
</body>
</html>
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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
<style>
*{
margin: 0px;
padding: 0px;
}
.box{
width: 300px;
height: 150px;
background-color: skyblue;
}
button{
width: 50px;
height: 25px;
}
.box1{
width: 300px;
height: 150px;
margin: 10px 0;
background-color: pink;
}
</style>
</head>
<body>
<!-- 定义的容器 -->
<div id="app">
<!-- 使用组件就相当于使用标签 -->
<Count></Count> <br>
<Count></Count> <br>
<Count></Count> <br>
<Count></Count> <br>
<Count></Count> <br>
<Box></Box> <br>
<Box></Box> <br>
<Box></Box> <br>
<Box></Box> <br>
</div>
<script>
let Hello = Vue.extend({
template: "<h1>我是Hello组件</h1>"
})
let Count = Vue.extend({
components:{
Hello
},
data(){
return{
count:0
}
},
methods:{
add(){ this.count++ },
minus(){ this.count-- }
},
template: `
<div class="box">
<Hello></Hello>
<button @click="minus">-</button>
<span>{{count}}</span>
<button @click="add">+</button>
</div>
`
})
let Box = Vue.extend({
data(){
return{
f:16
}
},
template:`
<div class="box1">
<p :style="{fontSize:f+'px'}" @click="f++">我是一个孤独的P标签</p>
</div>
`
})
let vm = new Vue({
el: "#app",
components:{
Count,
Box
},
data() {
return {
}
}
});
</script>
</body>
</html>
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
为什么组件的响应式务必要书写为函数
<script>
function data() {
return {
a: 1
};
}
let c1 = data();
let c2 = data();
c1.a = 100;
console.log(c1 === c2);
console.log(c1, c2);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 1.3, 根组件的template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!-- 定义的容器 -->
<div id="app">
<div>我是一个DIV</div>
</div>
<script>
// 对于根组件来说,可以在两个地方,指定模板
// 1)el对应容器内部的html代码段
// 2)配置template,用来指定模板
// 如果指定了template,它的优先级更高
let vm = new Vue({
el: "#app",
template:`
<div>haha</div>
`,
data() {
return {
}
}
});
vm.$mount("#app")
</script>
</body>
</html>
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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!-- 定义的容器 -->
<div id="app">
</div>
<script>
// 定义Count组件
const Count = Vue.extend({
data() {
return {
count: 1
};
},
template: `
<div>
<button @click="count++">加</button>
<span>{{count}}</span>
<button @click="count--">减</button>
</div>
`
});
// 定义Box组件
const Box = Vue.extend({
data() {
return {
f: 16
};
},
template: `
<div>
<p :style="{fontSize:f+'px'}" @click="f+=10">I love Vue!!!</p>
</div>
`
})
// 定义App组件
const App = Vue.extend({
components:{
Count,
Box
},
template:`
<div>
App组件
<hr>
<Count></Count>
<Count/>
<hr>
<Box/>
<Box/>
</div>
`
})
let vm = new Vue({
components:{
App
},
template:`
<div>
<App></App>
</div>
`,
data() {
return {
}
}
});
vm.$mount("#app")
</script>
</body>
</html>
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
83
84
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
83
84
# 1.4, 全局注册组件
定义为全局组件 : 定义一次, 可以在任意地方直接使用,不需要注册。
- 第一个参数:全局组件的名字(字符串) 第二个参数: 组件(不能书写为字符串)
- 全局组件一般在这种情况下才会使用: 项目当中很多地方(组件),大家频繁使用某一个功能
- 你就可以把这个功能封装为全局组件,定义一次,可以在任意地方直接使用【不需要引入、不需要注册】直接使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!-- 定义的容器 -->
<div id="app1">
<div>
我是DIV1
<hr>
<Count></Count>
</div>
</div>
<div id="app2">
<div>
我是DIV2
<hr>
<Count></Count>
</div>
</div>
<script>
// 定义Count组件
const Count = Vue.extend({
data() {
return {
count: 1
};
},
template: `
<div>
<button @click="count++">加</button>
<span>{{count}}</span>
<button @click="count--">减</button>
</div>
`
});
// 注册组件分两种:
// 1)局部注册 在哪里注册,在对应的模板中使用
// 2)全局注册 只需要注册一次,可以在任何地方使用
// 全局注册 在项目中,有些组件为了使用方法,都会使用全局注册
Vue.component("Count",Count)
let vm1 = new Vue({
el:"#app1",
// components:{
// Count
// },
data(){
return {
}
}
});
let vm2 = new Vue({
el:"#app2",
// components:{
// Count
// },
data(){
return {
}
}
});
</script>
</body>
</html>
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
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
# 1.5, VM与组件的关系
Vue框架中组件, 实质是Vue.extend函数返回的构造函数VueComponent
- 组件它是一个构造函数,那么在使用组件的时候,不应该new Student,咱们不需要手动去调用
- Vue框架查看网页, 看到了
标签,Vue框架帮你new VueComponent
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!-- 定义的容器 -->
<div id="app">
</div>
<script>
// 定义Count组件
// extend返回一个构造函数,叫VueComponent
const Count = Vue.extend({
data() {
return {
count: 1
};
},
template: `
<div>
<button @click="count++">加</button>
<span>{{count}}</span>
<button @click="count--">减</button>
</div>
`
});
// VueComponent VueComponent是一个类,构造器
// 按理说,我们需要去new VueComponent 得到一个普通组件实例
// 但是我们没有new Vue底层会帮我们new
// 一个组件说白了,也是一个对象,只不过这个对象不需要我们去new
console.log(Count);
// c叫组件对象 这是我们new出来的
let c = new Count();
// 也可以使用Vue原型对象上的属性或方法
console.log(c.$data);
// Vue vm VueCompoent vc
// Vue也叫类,也叫构造器
// new Vue得到一个vm实例
let vm = new Vue({
el: "#app",
data() {
return {
a:1
}
}
});
// console.log(vm.$data);
</script>
</body>
</html>
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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!-- 定义的容器 -->
<div id="app">
<Student></Student>
</div>
<script>
Vue.prototype.coding = function(){
console.log("开始打代码了...");
}
// 当我们使用Vue.extend 得到一个VueComponent构造器
// 不需要我们new Vue底层会帮我们new
let Student = Vue.extend({
data() {
return {
info: 'I love Vue!!!'
};
},
template: `
<h1 @click="changeInfo">{{info}}</h1>
`,
methods: {
changeInfo() {
// this.info = "I love React!!!"
// 问:this是谁?
// 答:vc
// 组件内的this,不是vm,不是vm,不是vm,是VueComponent类的实例
// 看上去和vm很像,但实际上,两者是不同东西
// 组件内的this,就是VueComponet类的实例,可以叫它VC
// this.coding();
console.log(this.__proto__.__proto__ === Vue.prototype);
}
}
});
let vm = new Vue({
el: "#app",
components:{
Student
},
data() {
return {
a: 1
}
},
methods:{
ok(){
// this表示vm
console.log(this);
}
}
});
</script>
</body>
</html>
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
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
Vue.extend创建组件简写方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入Vue.js,人家向外暴露一个Vue类 new Vue -->
<script src="../lib/vue2.7.8.js"></script>
</head>
<body>
<!-- 定义的容器 -->
<div id="app">
<!-- <Abc></Abc> -->
<App></App>
</div>
<script>
// 是Vue.extend的简写形式
// 定义组件
let App = {
// 为了在调试工具中显示正确的组件名,通常会配置name选项
name:"App",
data(){
return{
name:"wc"
}
},
template:`
<div>
<h1 @click="handler">{{name}}</h1>
</div>
`,
methods:{
handler(){
this.name = "xq";
console.log(this);
}
}
}
let vm = new Vue({
el:"#app",
components:{
// Abc表示注册名 App表示组件名
// "Abc":App
App
},
data(){
return {
}
}
});
</script>
</body>
</html>
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
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