Vue 组件化-父子组件通讯

🎉 父传子 props?

但是,在开发中,往往一些数据确实需要从上层传递到下层:

比如在一个页面中,我们从服务器请求到了很多的数据。

其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。

这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。

官方提到:

① 通过 props 向子组件传递数据

② 通过事件向父组件发送消息

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app" >
<cpn :cmovie="movie" :cmessage="message"></cpn>
</div>
</body>
<template id="cpn" >
<div>
<h1>{{cmessage}}</h1>
<h1>{{cmovie}}</h1>
</div>
</template>
<script type="text/javascript">
const cpn = {
template:'#cpn',
props: ['cmovie','cmessage'],
data(){
return {}
}
}
const app = new Vue({
        el:'#app',
        data:{
            message:'你好!',
movie: ["海王","海贼王","海盗王","赶海王"]
        },
components:{
cpn
}
    })
</script>
</html>

常见的 props 写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1.可以传递一个数组
props:["1","2","3"]
2.可以传递一个对象
props:{
apple:String,
numbers:Number,
}
3.可以提供初始值,以及必传值
props:{
apple:{
type:String,
default:"山东枣庄大苹果",
required:true
},
members:{
type:Array,
default(){
return []
},
required:true
},

🎉 验证都支持哪些数据类型呢?

String

Number

Boolean

Array

Object

Date

Function

Symbol

🎉props 的驼峰标识?

在绑定时 v-bind 不支持驼峰标识,

在绑定 cIndex 等具有驼峰标识的属性时

通过以下写法进行转换

1
:c-index //利用-替换驼峰

🎉 子传父 props?

props 用于父组件向子组件传递数据,

还有一种比较常见的是子组件传递数据或事件到父组件中。

我们应该如何处理呢?

这个时候,我们需要使用自定义事件来完成。

什么时候需要自定义事件呢?

当子组件需要向父组件传递数据时,就要用到自定义事件了。

我们之前学习的 v-on 不仅仅可以用于监听 DOM 事件,也可以用于组件间的自定义事件。

自定义事件的流程:

在子组件中,通过$emit()来触发事件。

在父组件中,通过 v-on 来监听子组件事件。

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app" >
<cpn @itemclick="cpnclick"></cpn>
</div>
</body>
<template id="cpn" >
<div>
<button v-for="item in cata" @click="itemclick(item)">{{item.name}}</button>
</div>
</template>
<script type="text/javascript">
const cpn = {
template:'#cpn',

data(){
return {
cata:[
{id:"aaa",name:"大圣归来"},
{id:"bbb",name:"大鱼海棠"},
{id:"ccc",name:"哪吒"},
{id:"ddd",name:"火影忍者"},
]
}
},
methods:{
itemclick(item){
console.log(item);
//发射,这里使用的是$emit
this.$emit('itemclick',item)
}
}
}
const app = new Vue({
        el:'#app',
        data:{
            message:'你好!',
movie: ["海王","海贼王","海盗王","赶海王"]
        },
components:{
cpn
},
methods:{
cpnclick(item){
console.log(item.name);
}
}
    })
</script>
</html>

🎉 父子组件通信案例?

通过子组件将数据读取再通过 input 改变后返回给父组件,

并将改变的值再次传入子组件中。

注意要点,

首先需要在改变子组件值的时候使用子组件的 data 进行一步中转,

然后在传回父组件时,对 v-model 进行拆解,将 input 事件进行抽离。

再通过$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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--
这里首先通过绑定父组件的data(num1和num2);
再通过子组件传递的自定义事件调用父组件中的方法。
-->
<cpn :number1="num1" :number2="num2"
@numberchange1="numberchange1"
@numberchange2="numberchange2"
></cpn>
</div>
<template id="cpn">
<div>
<h2>
props:{{number1}}
data:{{datanum1}}
</h2>
<input :value="datanum1" @input="inputnum1">
<!--将v-model进行拆分绑定,绑定value和监听input事件-->
<h2>
props:{{number2}}
data:{{datanum2}}
</h2>
<input :value="datanum2" @input="inputnum2">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好!',
num1: 1,
num2: 2
},
methods: {
numberchange1(value){
this.num1 = parseInt(value)
} ,
numberchange2(value){
this.num2 = parseInt(value)
} ,
},
components: {
cpn: {
template: '#cpn',
props: {
number1: Number,
number2: Number
},
data(){
return {
datanum1:this.number1,
datanum2:this.number2,
//这里需要对props的数据进行一次复用
//不能直接使用props的数据
}
},
methods:{
inputnum1(event){
this.datanum1 = event.target.value;
this.$emit("numberchange1",this.datanum1)
//发射数据
},
inputnum2(event){
this.datanum2 = event.target.value;
this.$emit("numberchange2",this.datanum2)
},
}
}
}
})
</script>
</body>