Vue组件

全局组件

模板

1
2
3
4
5
6
7
8
9
10
11
var Vue = Vue.extend({
el:'body',
data(){
return{
msg:'1'
}
},
template:'阳宁的博客' //写自己需要的代码
});

Vue.component('自己定义的标签名字',Vue)

需要用template定义自己需要的元素,然后用component进行全局注册。若定义的标签名字为aaa,则在html中可以如此调用;

1
2
<aaa></aaa>
<aaa></aaa>

这样就会出现如下情况:

阳宁的博客
阳宁的博客

这也是Vue组件的特点之一,它可以将需要的代码零件组合在一起封装成一个成品,在html中只需要用自己定义的标签即可实现代码的重用

data的不同

需要注意的是
组件中的data不同于实例化Vue的data,组件里的data必须是一个函数。若想要输出内容,用return输出即可。如下:

1
2
3
4
5
6
data(){
return{
msg:'1',
msg2:'2'
}
}

局部组件

若用Vue.component,可以在全局下调用组件。相应的,也会有局部组件,只能在局部作用域下使用组件。而局部组件写法如下:

1
2
3
4
5
6
new Vue({
el:'局部作用域',
components:{
标签名: 组件内容
}
})

注意

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
new Vue({
el:'.div1',
data:{
msg2:'123'
},
components:{
'aaa':{
data(){
return {
msg:'你好我是局部组件!'
}
},
methods:{
add(){
this.msg = '呵呵呵呵'
}
},
template:`<h1>
我是里面的组件
<input @click='add' type='button' value='aaa'>
{{msg}}{{msg2}} </h1>`
}
}
})

当在component外的data中定义了一个msg2,想要在components中用template来获取是做不到的,template只能拿到名为‘aaa’中的东西,外部的data是拿不到的。这个对于方法来说也是一样的,若想在template的标签中绑定一个名为add的函数,那么这个函数的定义也应该写在‘aaa’的定义下。

动态组件

通过使用保留的 <component>元素,动态地绑定到它的 is 特性,可以实现组件的动态切换。

1
2
3
4
<div id="example">
<button @click="change">切换页面</button>
<component :is="currentView"></component>
</div>

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
var home = {template:'<div>我是主页</div>'};
var post = {template:'<div>我是提交页</div>'};
var archive = {template:'<div>我是存档页</div>'};
new Vue({
el: '#example',
components: {
home,
post,
archive,
},
data:{
index:0,
arr:['home','post','archive'],
},
computed:{
currentView(){
return this.arr[this.index];
}
},
methods:{
change(){
this.index = (++this.index)%3;
}
}
})
</script>

如例子,在component标签用is绑定了计算属性中的currentView函数,当点击切换页面的按钮时,就会动态的改变函数返回的值,实现component标签中的内容进行动态改变。

父子级组件之间的通信

prop

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。
如以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Child = {
template: `<span >{{message}}{{myMessage}}</span>`,
//声明当前组件内部能够接受一个message的属性,如果是驼峰式命名,在传递参数时使用小写,
props: ['message','myMessage']
}
var vm = new Vue({
el: '#app',
data: {
parentMessage:'h'
},
components: {
Child
}
})

html中:

1
2
3
<child message="hello" :my-message="parentMessage"></child>//父组件赋值到子组件
<child message="hi"></child>
<input type="text" v-model="parentMessage"/>//实时同步的pareMessage值

$emit

当父级组件需要子级组件的数据时,若直接由父级组件去拿子级组件的数据,是具有一定的不确定性的,因为并不知道子级组件是否存在。所以传递模式应该为子级组件给出数据,再由父级组件去拿。要做到这些,就需要$emit以及事件去支撑。

子组件
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>
子组件:
<span>{{childValue}}</span>
<!-- 定义一个子组件传值的方法 -->
<input type="button" value="点击触发" @click="childClick">
</div>
</template>
<script>
export default {
data () {
return {
childValue: '我是子组件的数据'
}
},
methods: {
childClick () {
// childByValue是在父组件on监听的方法
// 第二个参数this.childValue是需要传的值
this.$emit('childByValue', this.childValue)
}
}
}
</script>
父组件
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
<template>
<div>
父组件:
<span>{{name}}</span>
<br>
<br>
<!-- 引入子组件 定义一个on的方法监听子组件的状态-->
<child v-on:childByValue="childByValue"></child>
</div>
</template>
<script>
import child from './child'
export default {
components: {
child
},
data () {
return {
name: ''
}
},
methods: {
childByValue: function (childValue) {
// childValue就是子组件传过来的值
this.name = childValue
}
}
}
</script>

$emit(‘接收数据的变量的名字,可自由起名’, 子组件中需要传递的数据)

slot

假设我们定义了这样一个组件:

1
2
3
4
5
components: {
children: {
template: '#aaa'
}
}

在html文本中这样子调用:

1
2
3
4
5
6
<children>
<h1>房子着火了</h1>
</children>
<template id='aaa'>
<h1>下雪了</h1>
</template>

打开html,我们会看到只有下雪了这一行文本,而在children标签中添加的html代码是不起作用的,这个时候就需要slot。

1
2
3
4
5
6
7
<children>
<h1>房子着火了</h1>
</children>
<template id='aaa'>
<h1>下雪了</h1>
<slot></slot>
</template>

这时再打开html时就会显示下雪了,房子着火了两行文本。
我们在组件当中可以放入任何的html代码,但如果想要让它们显示出来的话,需要使用slot标签,标签会替代你放在组件中的html代码。

更精准地使用slot

1
2
3
4
5
6
7
8
9
<children>
<h1 slot='h1-slot'>房子着火了</h1>
<h2 slot='h2-slot'>火车晚点了</h2>
</children>
<template id='aaa'>
<h1>下雪了</h1>
<slot name='h2-slot'></slot>
<slot name='h1-slot'></slot>
</template>

我们可以在标签中定义一个名为slot的属性,并将属性的值绑定到slot标签的name属性之中,如上文代码,文本会以
下雪了
火车晚点了
房子着火了
这样子的顺序排列。