在 Vue 中,组件之间的传值方式主要包括以下几种情况:
1. 父组件向子组件传值(props
)
父组件通过 props
传递数据给子组件:
<!-- Parent.vue -->
<template><ChildComponent :msg="message" />
</template><script>
import ChildComponent from './ChildComponent.vue';
export default {components: { ChildComponent },data() {return {message: 'Hello from Parent!'};}
};
</script>
<!-- ChildComponent.vue -->
<template><p>Received message: {{ msg }}</p>
</template><script>
export default {props: {msg: String}
};
</script>
2. 子组件向父组件传值($emit
)
子组件通过 this.$emit
触发事件,父组件监听事件并获取值:
<!-- Parent.vue -->
<template><ChildComponent @update-message="handleMessage" /><p>Message from Child: {{ receivedMessage }}</p>
</template><script>
import ChildComponent from './ChildComponent.vue';
export default {components: { ChildComponent },data() {return {receivedMessage: ''};},methods: {handleMessage(msg) {this.receivedMessage = msg;}}
};
</script>
<!-- ChildComponent.vue -->
<template><button @click="sendMessage">Send to Parent</button>
</template><script>
export default {methods: {sendMessage() {this.$emit('update-message', 'Hello from Child!');}}
};
</script>
3. 兄弟组件传值(Event Bus
或 Pinia/Vuex
)
兄弟组件需要一个中间桥梁,比如 Event Bus
(Vue 3 不推荐)或 Pinia
(推荐):
// eventBus.js (Vue 2 可用,Vue 3 推荐使用 Pinia)
import Vue from 'vue';
export const EventBus = new Vue();
在 BrotherA.vue
发送数据:
<template><button @click="sendMessage">Send to BrotherB</button>
</template><script>
import { EventBus } from './eventBus.js';
export default {methods: {sendMessage() {EventBus.$emit('message', 'Hello from BrotherA!');}}
};
</script>
在 BrotherB.vue
接收数据:
<template><p>{{ receivedMessage }}</p>
</template><script>
import { EventBus } from './eventBus.js';
export default {data() {return { receivedMessage: '' };},created() {EventBus.$on('message', msg => {this.receivedMessage = msg;});}
};
</script>
4. ref
方式(获取子组件实例)
父组件可以通过 ref
获取子组件实例并访问其方法或数据:
<!-- Parent.vue -->
<template><ChildComponent ref="childRef" /><button @click="callChildMethod">Call Child Method</button>
</template><script>
import ChildComponent from './ChildComponent.vue';
export default {components: { ChildComponent },methods: {callChildMethod() {this.$refs.childRef.childMethod();}}
};
</script>
<!-- ChildComponent.vue -->
<template><p>Child Component</p>
</template><script>
export default {methods: {childMethod() {console.log('Child method called!');}}
};
</script>
5. provide
和 inject
(适用于祖孙组件)
适用于跨层级组件通信:
<!-- GrandParent.vue -->
<template><Parent />
</template><script>
import Parent from './Parent.vue';
export default {components: { Parent },provide() {return { sharedMessage: 'Hello from GrandParent!' };}
};
</script>
<!-- Parent.vue -->
<template><Child />
</template><script>
import Child from './Child.vue';
export default {components: { Child }
};
</script>
<!-- Child.vue -->
<template><p>{{ sharedMessage }}</p>
</template><script>
export default {inject: ['sharedMessage']
};
</script>
6. Vuex 或 Pinia(全局状态管理)
适用于复杂状态管理,如 Vuex(Vue 2)或 Pinia(Vue 3):
// store.js (使用 Pinia)
import { defineStore } from 'pinia';export const useMainStore = defineStore('main', {state: () => ({message: 'Hello from Store'}),actions: {setMessage(newMsg) {this.message = newMsg;}}
});
在 ComponentA.vue
更新数据:
<template><button @click="updateMessage">Update Message</button>
</template><script>
import { useMainStore } from './store.js';
export default {setup() {const store = useMainStore();const updateMessage = () => store.setMessage('Updated Message!');return { updateMessage };}
};
</script>
在 ComponentB.vue
读取数据:
<template><p>{{ store.message }}</p>
</template><script>
import { useMainStore } from './store.js';
export default {setup() {const store = useMainStore();return { store };}
};
</script>