非单文件组件

组件分为:非单文件组件和单文件组件

非单文件组件:一个文件中包含有n个组件,通过html文件管理

单文件组件:一个文件中只包含有1个组件,如.vue文件

1.基本使用组件

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
/*
Vue中使用组件的三大步骤:
1.创建组件
2.注册组件
3.使用组件
*/

// 1.创建组件 Vue.extend({})方法创建
const simple = Vue.extend({
template:`<div>{{name}}</div>`
data(){
return { name: 'simplelife'}
},
methods:{}
})

// 2.注册组件,让根组件管理子组件
const vm = new Vue({
el:'#demo',
data:{},
components:{
simple(组件名):simple(创建名) //=> 同名可以使用ES6简写方式
}
})

// 3.使用组件
// 假设这段是 Vue接管的容器
<div id="demo">
<simple></simple>
</div>

2.Vue.extend({})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1.创建组件可以省略 Vue.extend
// 省略并不是没使用这个函数,而是当被注册的时候,才会调用这个函数
const simple = {
template:``,
data(){}
}

// 2.创建的组件,不需要填写 el 属性,其它和new Vue一样
// 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
// data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。

// 3.组件创建还有一个 `name` 属性
// 这个名字是用于 devTools 工具展示的名称,用于区别模块
const simple = {
name: 'SimpleLife'
template:``,
data(){}
}

// 4.创建的组件,谁注册谁能使用
// 局部注册:靠new Vue的时候传入components选项

3.全局组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 如上称为局部组件,谁注册谁就能用
// 1.创建组件构造器对象
// 全局注册:靠Vue.component('组件名',组件)
const cpnConstruct = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容</p>
</div>
`
})//使用的tab健的引号,ES6语法,作用跟双引号单引号一样,但是可以换行

//2.注册组件
Vue.component('my-cpn',cpnConstruct);

//3.使用组件(在Vue的实例范围内使用组件)
<div id="app">
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>

4.注意事项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!--
1.关于组件名命名规范:
一个单词组成:
第一种写法(首字母小写):simple
第二种写法(首字母大写): Simple
多个单词组成:
第一种(kebad-case命名): my-simple
第二种(CamelCase命名): MySimple(需要脚手架才能解析这种命名)
备注:
(1). 组件名避免HTML已有的元素名称,否则解析失败,按正常HTML标签解析
(2). 可以使用name配置项指定组件在开发者工具(devtool)中呈现的名字
2.关于组件标签:
第一种写法:<simple></simple>
第二种写法:<simple/>
备注:不使用脚手架时,<school/>会导致后续组件不能渲染。

-->

5.组件嵌套使用(父子组件)

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
/*
* 子组件生命必须在父组件之前,由上自下
* 创建Vue实例对象vm,再创建app组件,去替代vm接管子组件
* 因此 school 组件生命在 app 组件里面
* school子组件 student 组件,声明在school里面
* 这种使用就是组件嵌套使用
*/
//定义student组件
const student = Vue.extend({
name:'student',
template:`
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
name:'simplelife',
age:18
}
}
})

//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return {
name:'simplelife',
address:'江西'
}
},
//注册组件(局部)
components:{
student
}
})

//定义app组件
const app = Vue.extend({
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
components:{
school,
}
})

//创建vm
new Vue({
template:'<app></app>',
el:'#root',
//注册组件(局部)
components:{app}
})

VueComponent

1
2
3
4
5
6
7
8
//定义school组件
const school = Vue.extend({
name:'school',
template:``
})

// school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
// 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!

1.关于this指向

  1. 组件配置中:

    data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。

  2. new Vue(options)配置中:

    data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

2.重要的内置关系

VueComponent.prototype.__proto__ === Vue.prototype

为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

单文件组件

单文件组件由Vue创建的.vue文件,里面有三种标签<template><script><style>

1.组件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
<template>
<!--html-->
<div id="">

</div>
</template>

<script>
// JS代码
// ES6模块化导出三种方式
export const simple = Vue.extend({})

export {
simple
}

export default simple // 常用该默认导出

// Vue.extend 之前解释过可以省略,最后Vue会帮我们调用Vue.extend()

// 常用导出形式
export default {
name:'Simple',
data(){ return {} }
}
</script>

<style>
/*CSS样式,只对当前组件有效*/
</style>

2.App文件管理组件

1
2
3
4
5
6
7
8
9
10
11
12
<!--
将所有的组件,通过App组件来接管
和嵌套组件的方式差不多,只是需要导入组件 通过 `import xxx form './xxx'`
-->

<script>
import Simple form './Simple.vue';
export default {
name:'Simple',
data(){ return {} }
}
</script>

3.创建Vue实例 main.js

1
2
3
4
5
6
7
8
// Vue选择一个文件命名 main.js 来管理vm
// 只需要导入一个大组件
import App form './App.vue';

new Vue({
el:'#root',
components:{App}
})

4.index.html使用组件

1
2
3
4
5
<div id="root">
<App></App>
<!-- 如果不想引用组件,可以在main.js,将vm实例的template属性写入 `<App>` -->
</div>
<!--引入相关JS,在引入Vue.js后,引入main.js-->

PS:目前一切就绪,但是浏览器无法识别ES6语法,更无法加载.vue文件,因此需要打包工具 webpack

初期组件模板分离

抽离组件模板,将模板放置在其它地方,我们将使用两种方法,来抽离。

<script>标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="root">
<demo></demo>
</div>
<!--
将模板通过 `script` 脚本标签展示
-->
<script type="text/x-template" id="demo">
<div>
<h2>{{message}}</h2>
</div>
</script>

<script>
Vue.component('demo',{
template:'#demo',
data(){ return {message:'simplelife'}}
})

//注册根组件省略
</script>

<template>标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="root">
<demo></demo>
</div>
<!--
将模板通过 `template` 标签展示
-->
<template id="demo">
<div>
<h2>{{message}}</h2>
</div>
</template>

<script>
Vue.component('demo',{
template:'#demo',
data(){ return {message:'simplelife'}}
})

//注册根组件省略
</script>

PS:通过脚手架帮我们构建项目,会非常便捷,且易维护。这种早期非单文件分离模板的做法,显然已不再使用

Vue组件数据 data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
Vue组件数据data必须是函数,以保证组件复用性
通过案例,更改的解答问题
*/

// 示例一,对象形式
var obj = {
name: 'simplelife',
age: 18
}

var obj1 = obj
var obj2 = obj

// 通过 obj1 修改name 和 age
obj1.name = 'life'
obj1.age = 20

console.log(obj1) // 打印结果 { name: 'life' , age:20}
console.log(obj2) // 打印结果 { name: 'life' , age:20}

// 显然 obj2中的对象也被更改了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 示例二,函数形式
function getName(){
return {
name: 'simplelife',
age: 18
}
}

var test1 = getName()
var test2 = getName()

// 通过 obj1 修改name 和 age
test1.name = 'life'
test1.age = 20

console.log(obj1) // 打印结果 { name: 'life' , age:20}
console.log(obj2) // 打印结果 { name: 'lsimplelifeife' , age:18}

// 此时修改不会影响到其它的组件,这样就可以放心的复用组件