什么是组件
实现应用中局部功能代码和资源的集合
组件化编程的好处
- 依赖关系更加清晰
- 代码复用率更高(不仅仅是js和css,html结构也被复用了)
非单文件组件和单文件组件
什么是非单文件组件和单文件组件,看下图:
简而言之,非单文件组件是一个html文件,里面使用到多个组件,单文件组件是一个vue文件,本身代表一个组件
非单文件组件的使用
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非单文件组件</title>
<script src="./js/vue.js"></script>
<style>
/* 中间如果不加',',表示的是后代元素,加了才表示两个没有关系的class */
.mytitle, .text {
font-size: 50px;
}
</style>
</head>
<body>
<div id="app">
<!-- 3.使用组件 -->
<list></list>
</div>
</body>
<script>
// 1.定义组件
const myList = Vue.extend({
// el:'#app',不需要挂载容器,毕竟组件作为复用对象是要被用在不同的地方,而且它是由Vue实例进行统一管理的
// 1-1.组件结构,template结构必须有一个root element,即整个template需要用容器包裹,这个容器可以是任意的
template: `
<div>
<p class='mytitle' v-text='title'></p>
<ul>
<li class='text' v-for='food in foods'></li>
</ul>
</div>
`,
// 1-2.数据对象必须用函数式,因为函数式每次返回不同的对象,那么就不存在改了值大家都变了的结果
data() {
return {
title: '食谱',
foods: ['青椒炒肉', '水煮鱼片', '宫保鸡丁']
}
}
});
// 2.注册组件
new Vue({
components: {
// 左边的组件名中间不能有大写字母,如果左右名称相同,就可以省略冒号和右边
list: myList
},
}).$mount('#app');
</script>
</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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非单文件组件</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<!-- 2-1.最终在html结构中,我们不需要写任何代码,这样非常的清晰 -->
<div id="app">
</div>
</body>
<script>
// 1.定义组件
const list = Vue.extend({
// 1-1.列表组件
template: `
<div>
<p class='mytitle' v-text='title'></p>
<ul>
<li class='text' v-for='food in foods'></li>
</ul>
</div>
`,
data() {
return {
title: '食谱',
foods: ['青椒炒肉', '水煮鱼片', '宫保鸡丁']
}
}
});
const mybutton = {
// 1-2.按钮组件
template: `
<Button type="submit">提交</Button>
`
}
const myinput = {
// 1-3.输入框组件
template: `
<input type='text' value='请输入值' />
`
}
const app = {
// 1-4.母组件
template: `
<div>
<mylist></mylist>
<myinput></myinput><br>
<mybutton></mybutton>
</div>
`,
// 1-5.app统一管理子组件
components:{
mybutton,
myinput,
mylist:list
}
}
// 2.注册组件
new Vue({
template: `
<app></app>
`,
// vm管理母组件
components: {
app
},
}).$mount('#app');
</script>
</html>
像下面的这种结构:
我们称其为标准化开发
VueComponent构造函数
深入理解组件
一个重要的内置关系
在javascript中存在一种被称作原型链的关系,其中实例对象的属性__proto__
会指向它的上级,它对应的构造函数的属性prototype也会指向实例对象的上级
而在Vue中,有这样一个重要的内置关系:VueComponenet.prototype.__proto__ == Vue.prototype,而这个关系的存在使得组件实例对象(vc)可以访问到Vue原型上的属性和方法
单文件组件
单文件组件以.vue结尾,最终会被编译成.js,单文件的基本组成结构
1
2
3
4
5
6
7
8
9
10
11
<template>
// 组件的结构,template最终会被消掉,留下里面的东西
</template>
<script>
// 相关的资源和交互逻辑代码
</script>
<style>
// 样式
</style>
非单文件组件与单文件组件相比他不能为每个组件分组独立的css,这是它的缺陷,也是单文件组件的优点
单文件组件示例
List.vue
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
<template>
// 1.注意外面一定要用root元素包裹
<div>
<p class='mytitle' v-text='title'></p>
<ul>
<li class='text' v-for='food in foods'></li>
</ul>
</div>
</template>
<script>
// 2.组件需要被暴露,才能被外界使用
// 第一种写法,分别暴露
// export const list = {
// data() {
// return {
// title: '食谱',
// foods: ['青椒炒肉', '水煮鱼片', '宫保鸡丁']
// }
// },
// methods: {
// }
// }
// 第二种写法,统一暴露
// export {list}
// 第三中方式,默认暴露
// export default list
// 或者下面这样
export default {
name: List,
data() {
return {
title: '食谱',
foods: ['青椒炒肉', '水煮鱼片', '宫保鸡丁']
}
},
methods: {
}
}
</script>
<style>
</style>
App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div>
// 4.实例化组件
<List></List>
</div>
</template>
<script>
// 1.引入子组件,.vue在脚手架中可以忽略
import List from './List.vue'
// 2.组件需要被暴露,才能被外界使用
export default {
name: App,
// 3.注册组件
components:{
List
}
}
</script>
<style>
</style>
main.js
1
2
3
4
5
6
7
8
9
10
import App from './App.vue'
new Vue({
el:'#root',
// 在这里写了
template:`<App></App>`
components:{
App
}
})
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>测试</title>
</head>
<body>
<div id="root"></div>
<!-- 1.main.js使用了Vue,所以在它之前需要引入vue.js -->
<script src="./js/vue.js"></script>
<!-- 2.由于main.js使用了root元素,因此必须在其后引入 -->
<script src="./main.js"></script>
</body>
</html>
分别暴露和统一暴露被外界引用时格式:import {XXX} from YYY,而默认暴露是:import XXX from YYY,所以我们推荐使用默认暴露,因为它更加简洁