组件通讯
组件之间的耦合是通过组件之间通过传递消息、相互配合才能完成对应的功能完成的。通过一个良好定义的接口来尽可能将父子组件解耦也是很重要的,保证了每个组件的代码可以在相对隔离的环境中书写和理解,也提高了其可维护性和复用性。组件之间的通讯包括父子组件之间通讯及组件与组件之间的通讯。
父子组件之间通讯
父子组件通讯:如果组件 A 在它的模板中使用了组件 B,则称A是B的父组件,B是A的子组件。父子组件通讯包括父组件给子组件传递消息及子组件则可能要将它内部发生的事情告知父组件两方面的通讯。
- 父组件给子组件传值:组件向子组件传值使用“props”完成。所传值可以单值,也可以多个值,传递多个参数时,建议使用json数组{}的形式进行传递。
【示例】:单值传递,父组件向子组件传递一个消息,此消息显示在子组件中,子组件代码如下:
<template>
<div class="active">
<span>{{v_info}}</span> //显示父组件的值
</div>
</template>
<script>
export default {
name: "v_child",
props: ['v_info'] //子组件定义一个名为v_info的属性,用于获取父组件传递过来的数据
}
</script>
在子组件定义props属性v-info用于接收父组件传入的值。子组件通过 props方法获取父组件传递过来的值。父组件使用代码如下:
<template>
<div class="alert-danger">
<input type="text" v-model='info' />
<v-child :v_info="info"></v-child> //通过v-bind将info数据与子组件的v_info属性绑定
</div>
</template>
<script>
import v-child from './commPropsChild'
export default {
name: "v-parent",
data() {
return {
info: "我是父组件的值"
}
},
components: {
v-child: v-child
}
}
</script>
将父组件中data中info属性值是要给子组件传送的数据,:v_info 是绑定的子组件在props属性定义的变量,其用法如: ,使用方式同HTML中的控件。使用props不仅可以传送单值,也可以传递数组和对象(以json格式)。子组件通过 props方法获取父组件传递过来的值数据类型的使用。如果不考虑数据类型,直接 props:[“v-age”,“v-adress”]就可以了,括号中包裹多个值,使用“,”分隔。props中也可以定义能接收的数据类型,这时如果传入的数据不符合会报错,还可以设置默认值。
【例】props传递数据类型
<script>
export default {
props:{
v-number:[Number,String], //限制v-number传递数据类型为Number或者String,数据类型不匹配报错
v-info:[String],//v-info数据类型必须是String
v-info2: {
type: String,
required: true // 组件使用时v-info2是必须赋值的字符串
},
v-info3: {
type: Number,
default: 100 //v-info3数据类型为数字,默认值为100
},
v-info4: {
type: Object,
default: function () { //v-info4数据类型为对象,具有默认值的对象
return { message: 'hello' }
}
}
v-info5: {
validator: function (value) {
return value > 10 // 自定义验证函数
}
}
}
}
</script>
注:父组件向子组件传值时,使用数据是异步请求,此时有可能渲染时数据还没有获取,导致渲染错误。具体解决办法:在父组件需要传递数据的节点加上v-if = false,获取数据后将v-if = true,进行数据传递。示例如下:
//引入的add-widget组件
<add-widget :msg-val="msg" v-if='dataReady'>
</add-widget> //这里dataReady的值是false,当获取完数据改为true,再给msg赋值
<script>
export default {
data(){
return {
msg: [1,2,3],
dataReady:false
};
methods{
getMsg(){
//执行提取数据
dataReady =true
}
}
}
</script>
- 子组件给父组件发消息。
子组件向父组件传值是通过emit事件完成。在子组件中使用语法:$emit(‘watchMethod’, childValue) 其中参数watchMethod是在父组件on监听的方法,第二个参数this.childValue是需要传的值。
【示例】点击子组件的按钮,将子组件的消息数据传递给父组件
子组件代码如下:
<template>
<div class="active">
<h1>子组件显示区</h1>
<input type='button' value='提交值给父组件'
@click="emitMethod" /> //按钮单击事件绑定emitMethod方法。
</div>
</template>
<script>
export default {
name: "v-child",
data() {
return {
childValue: '我是子组件的数据'
}
},
methods: {
emitMethod() { //方法定义
this.$emit('watchMethod', this.childValue)
}
}
}
<script>
子组件中“watchMethod”是子组件事件绑定接口方法的名称。
父组件代码如下
<template>
<div class="alert-danger">
<span>{{childvalues}}</span>
<appChild v-on: watchMethod="fatherMethod"></appChild>
//子组件watchMethod事件中绑定父类中fatherMethod
</div>
</template>
<script>
import v-child from './commPropsChild'
export default {
name: "v-parent",
data() {
return {
info: "我是父组件的值",
childvalues: ''
}
},
methods: {
fatherMethod: function(childValue) {
// childValue就是子组件传过来的值
this.childvalues = childValue
}
},
components: {
v-child: v-child
}
}
</script>
将父类组件的方法绑定到子类的定义的方法上,其参数就是子类给父类传递的信息。
小结
在VUE组件开发中,体现了面向对象封装性,父子组件之间的通讯使用props和emit,通过简单属性和方法的定义父组件与子组件内部完全脱耦,使得二者之间的耦合变得简单明确。父组件和子组件通讯还包括provide / inject API、插槽、vuex、eventbus、localStorage、#refs等形式,在后续章节再做介绍。接下来我们兄弟组件之间的通讯。