前言
在实际的项目开发过程中,很多业务逻辑里面,vue组件之间需要相互传递数据,传递数据用的就是组件通信。而不同的组件之间也可进行数据交流和信息传递的过程。
1.父子组件通信
所谓父子组件通信其实就是,父组件向子组件传递数据 或者 子组件向父组件传递数据的过程。
1.1 父组件向子组件传递数据
父组件向子组件传递数据:通过props属性,在父组件中向子组件传递数据,子组件可通过props接收传递过来的数据。
语法:
- 父组件使用
v-bind绑定动态数据到子组件的标签上
<子组件标签 :属性名="动态数据"></子组件标签>
- 子组件通过
props接收,接收的对象写法/类型校验/默认值
export default {
props:{
属性名: {
type:'', //类型可以是number/object/boolean/array/data/function等...
default:'' // 对象或者数组需要写函数
}
{
}
1.1.1 案例
假设有一个父组件parent和一个子组件Child,我们希望将message这个字符串传递给Child组件。
<template>
<div>
<Child :message="message" />
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {
Child //注册
},
data() {
return {
message: 'Hello from Parent'
};
}
}
</script>
在子组件Child中,我们可以通过props来接收来自父组件的数据。
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
props: ['message']
}
</script>
在上述例子中,父组件使用了":message"的绑定机制,将父组件中的"message"属性值传递给了子组件的props。子组件则通过定义props来接收该属性值,并可以在模板中使用。
需要注意的是,props是单向数据流,只能由父组件向子组件传递数据,并且子组件不能修改props中接收到的数据。如果需要在子组件中修改父组件的数据,可以通过自定义事件或Vuex等其他方法来实现。
1.2 子组件向父组件传递数据
子组件向父组件传递数据:通过在子组件中触发自定义事件,父组件监听该事件,并在监听回调中接收数据。$emit是Vue实例的一个方法,它用于向父组件触发自定义事件并传递数据。通过在子组件中调用$emit方法,可以触发父组件中相应的事件处理函数,并将数据传递过去。
语法:
- 子组件可通过
this.$emit()把数据传递出去
this.$emit("自定义事件", 要传递出去的数据)
- 父组件通过在子组件标签上
v-on绑定自定义事件接收数据
<子组件标签 @自定义事件="函数名"></子组件标签>
methods: {
函数名(sonData){
//sonData就是子组件传递过来的数据
}
}
1.2.1 使用$emit方法的步骤
- 在父组件中定义一个事件处理函数,用来接收子组件触发的事件和传递过来的数据。
<template>
<div>
<!-- 监听子组件的自定义事件 -->
<ChildComponent @custom-event="handleCustomEvent"></ChildComponent>
</div>
</template>
<script>
export default {
methods: {
// 定义事件处理函数
handleCustomEvent(data) {
// 处理接收到的数据
console.log(data);
}
}
}
</script>
- 在子组件中调用
$emit方法来触发父组件的事件,并将需要传递的数据作为参数传递。
<template>
<div>
<button @click="triggerEvent">触发事件</button>
</div>
</template>
<script>
export default {
methods: {
// 触发事件
triggerEvent() {
// 使用$emit触发父组件的自定义事件,并传递数据
this.$emit('custom-event', 'Hello from child component');
}
}
}
</script>
在这个案例中,当子组件中的按钮被点击时,triggerEvent方法会调用$emit方法触发父组件的custom-event事件,并将字符串 'Hello from child component' 作为参数传递给父组件的事件处理函数 handleCustomEvent。这样父组件监听到子组件触发的事件后,就可以执行相应的逻辑来处理接收到的数据。
总结起来,$emit方法是Vue.js中一种简单而有效的组件通信方式,通过自定义事件和数据的传递,实现了子组件向父组件的通信。
1.2.2 v-on 指令
v-on是Vue.js 框架中非常重要的一个指令,用于监听DOM事件并执行相应的事件处理函数。通过v-on指令,你可以在模板中直接绑定事件监听器。
其次;v-on指令也可以用于父组件中监听子组件触发的事件。通过v-on指令,可以在父组件中指定一个事件处理函数,并对子组件发出的特定事件做出反应。
基本用法:
最基本的用法是将v-on指令绑定到一个事件名上,并在等号后面指定一个需要调用的方法名。
<button v-on:click="handleClick">Click me</button>
// 当按钮被点击时,handleClick 方法会被调用
缩写方法:
Vue.js 还提供了一种缩写语法,将v-on指令缩写为@符号。
<button @click="handleClick">Click me</button>
// @click 缩写方式达到了和之前基本用法相同的效果
// 即当按钮被点击时,执行 handleClick 方法
传递参数
有时候你可能需要在事件处理函数中传递额外的参数,可以通过$event参数获取事件对象
<button @click="handleClick('param')">Click me</button>
// 点击按钮时会调用 handleClick 方法,并传递 'param' 字符串作为参数
动态事件名
在一些特殊情况下,你可能需要动态地绑定不同的事件名。可以通过使用计算属性或者直接在表达式中调用方法来实现。
<template>
<button v-bind:[Event]="handleEvent">Event</button>
</template>
<script>
export default {
data() {
return {
Event: 'click',
};
},
methods: {
handleEvent() {
console.log('Dynamic event handled');
},
},
};
</script>
在上面的示例中,Event 是一个动态属性,它的值会根据组件实例中的handleEvent方法动态变化,当点击按钮时,handleEvent方法会被调用。
修饰符
修饰符是附加到事件处理函数上的特殊后缀,用于修改事件的行为。Vue.js 提供了多种事件修饰符,例如 stop、prevent、capture、self、enter、space 等,可以按需使用。
<button @click.stop="handleClick">Stop event propagation</button>
当然v-on的作用不止于此,除了这些之外还可以配合$emit作用于父子组件之间的通信。而在这里面v-on指令可以用于父组件中监听子组件触发的事件。通过v-on指令,可以在父组件中指定一个事件处理函数,并对子组件发出的特定事件做出反应。v-on指令需要指定监听的事件和相应的处理函数,以 v-on:事件名="回调函数" 的形式来使用。除了使用 v-on:事件名,还可以简写为 @事件名。前面已有它的用法。
且来看一个案例:首先是父组件的代码
<!-- 父组件 -->
<template>
<div>
<!-- 监听子组件的自定义事件 -->
<ChildComponent @custom-event="handleCustomEvent"></ChildComponent>
</div>
</template>
<script>
export default {
methods: {
// 事件处理函数,接收子组件传递的数据
handleCustomEvent(data) {
console.log(data);
}
}
}
</script>
子组件代码
<!-- 子组件 -->
<template>
<div>
<button @click="triggerEvent">触发事件</button>
</div>
</template>
<script>
export default {
methods: {
// 触发自定义事件,并传递数据给父组件
triggerEvent() {
this.$emit('custom-event', 'Hello from child component');
}
}
}
</script>
在上面的示例中,当子组件中的按钮被点击时,triggerEvent方法会调用$emit方法触发父组件的custom-event事件,并将字符串 'Hello from child component' 作为参数传递给父组件的事件处理函数handleCustomEvent。
父组件通过使用v-on指令监听子组件触发的custom-event事件,并指定相应的事件处理函数handleCustomEvent来处理接收到的数据。
1.2.3 使用$emit与v-on方法实现组件之间的通信时的注意事项
- 父组件需要在模板中通过
v-on指令或者@符号来监听子组件触发的事件,并指定相应的事件处理函数。 - 事件名称要与子组件中使用
$emit方法时的事件名称保持一致。 - 在父组件中定义的事件处理函数可以接收传递过来的数据,通常我们会将数据作为参数传递给事件处理函数
总结:$emit方法用于子组件向父组件发送自定义事件,并将数据传递给父组件。v-on指令用于父组件监听子组件触发的事件,并执行相应的事件处理函数。这两种方法配合使用可以实现组件之间的双向通信。
2. 任意组件之间传递数据(跨级组件)
在vue中,我们可以使用一个空的vue实例作为中央事件的总线(event bus)来实现任意组件之间数据的传递。步骤如下:
- 首先,我们需要在入口文件
main.js中创建一个新的vue实例并且挂载到vue的原型上。以此作为事件的总线:
Vue.prototype.$bus = new Vue();
- 然后,在一个组件中,我们可以使用
$bus.$emit触发一个事件,将数据传递出去:
this.$bus.$emit('自定义事件', 要传递出去的数据);
- 在另外一个组件中,通过
vue的生命周期created中,通过$on监听自定义事件的方式,接收数据
created(){
this.$bus.$on(‘自定义事件’, function ( data ) {
// data就是从传递过来的数据
})
}
2.1 示例代码
把数据传递出去的组件代码
// Son.vue
<template>
<div class="son">
子组件
<br />
<button @click="sendToOther">发送给其他儿子</button>
</div>
</template>
<script>
export default {
data() {
return {
msg2: "来自儿子的数据",
msg: "任意组件间传递数据"
};
},
methods: {
sendToOther() {
// 把数据传递出去
this.$bus.$emit("atWill", this.msg);
}
}
};
</script>
<style lang="less" scoped>
.son {
color: green;
border: 1px solid green;
height: 100px;
}
</style>
接收数据的组件代码
<template>
<div class="other-son">
其他儿子组件
<br />
自己的:{{ msg }}
<br />
别的组件传过来的: {{ otherMsg }}
</div>
</template>
<script>
export default {
data() {
return {
msg: "其他儿子自己的数据",
otherMsg: ""
};
},
created() {
// 接收数据
this.$bus.$on("atWill", msg => {
this.otherMsg = msg;
});
}
};
</script>
<style lang="less" scoped>
.other-son {
margin-top: 20px;
border: 1px solid orange;
height: 150px;
}
</style>