Vue 父子组件通信:使用自定义事件实现子传父
Vue 组件间的数据反向传递
在 Vue 的组件化架构中,数据流默认是单向的,即通过 props 从父组件向子组件传递。然而,在实际开发中,子组件往往需要将内部状态或用户交互的结果反馈给父组件。这种"反向传递"可以通过自定义事件(Custom Events)来实现。
子组件通过内置的 $emit 方法触发一个自定义事件,父组件则通过 v-on(或简写 @)监听该事件并执行相应的回调函数。
基础组件搭建
假设我们有一个父组件 App.vue 和一个子组件 MessageSender.vue。首先,在父组件中引入并注册子组件。
MessageSender.vue (子组件)
<template>
<div class="sender-container">
<h3>子组件:消息发送器</h3>
</div>
</template>
<script>
export default {
name: "MessageSender"
};
</script>
App.vue (父组件)
<template>
<div id="app">
<MessageSender />
</div>
</template>
<script>
import MessageSender from './components/MessageSender.vue';
export default {
name: 'App',
components: {
MessageSender
}
};
</script>
触发与监听自定义事件
为了让子组件能够向父组件传递数据,我们需要在子组件中定义一个触发事件的方法,并使用 this.$emit 抛出事件。
更新 MessageSender.vue
<template>
<div class="sender-container">
<h3>子组件:消息发送器</h3>
<button @click="dispatchMessage">发送消息到父组件</button>
</div>
</template>
<script>
export default {
name: "MessageSender",
data() {
return {
payload: "这是一条来自子组件的加密数据"
};
},
methods: {
dispatchMessage() {
// 第一个参数是自定义事件名称,建议使用 kebab-case 命名
// 第二个参数是需要传递的数据载体
this.$emit("message-sent", this.payload);
}
}
};
</script>
在父组件中,我们将这个自定义事件当作原生 DOM 事件一样进行监听。
更新 App.vue
<template>
<div id="app">
<!-- 监听 message-sent 事件,并绑定处理函数 -->
<MessageSender @message-sent="processIncomingData" />
</div>
</template>
<script>
import MessageSender from './components/MessageSender.vue';
export default {
name: 'App',
components: {
MessageSender
},
methods: {
processIncomingData(receivedData) {
console.log("父组件接收到数据:", receivedData);
}
}
};
</script>
当点击子组件中的按钮时,dispatchMessage 方法被执行,触发 message-sent 事件。父组件监听到该事件后,调用 processIncomingData 方法,并将子组件传递的 payload 作为参数 receivedData 传入。
状态更新与视图渲染
通常,父组件接收到子组件的数据后,会将其更新到自身的响应式状态中,从而驱动视图的重新渲染。
最终版 App.vue
<template>
<div id="app">
<MessageSender @message-sent="processIncomingData" />
<div class="display-area" v-if="displayText">
<p>父组件展示区:{{ displayText }}</p>
</div>
</div>
</template>
<script>
import MessageSender from './components/MessageSender.vue';
export default {
name: 'App',
data() {
return {
displayText: ""
};
},
components: {
MessageSender
},
methods: {
processIncomingData(receivedData) {
// 将接收到的数据赋值给父组件的响应式属性
this.displayText = receivedData;
}
}
};
</script>
上述代码展示了如何将子组件传递的参数赋值给父组件的响应式属性 displayText,从而触发视图的自动更新。