Vue.js 2.5.13中如何在父组件获取子组件的数据?
Hey there! Let's tackle this component data sharing issue in Vue 2.5.13—since you're building a registration form with multiple components, it's crucial to pick the right approach that's maintainable and follows Vue's best practices. First, a quick note: in your component-two.vue, you have input_one in data() but your template uses v-model="input_two"—that's a typo! I'll fix that in the examples below.
Here are the top 3 methods to get ComponentTwo's data into ComponentOne:
1. Use ref to Directly Access the Child Component (Simple Read-Only Scenarios)
This is the quickest way for one-off data access, but it breaks Vue's one-way data flow principle (so avoid modifying child data via refs).
Update ComponentOne.vue:
Add a ref attribute to your <component-two> tag, then access the child's data via $refs:
<template> <div> <input type="text" v-model="input_one"> <!-- Add ref to the child component --> <component-two ref="componentTwo"></component-two> </div> </template> <script> import ComponentTwo from 'component-two.vue' export default { name: "component-one", components: { ComponentTwo }, data() { return { input_one: 'Hello from ComponentOne', input_two: '' } }, mounted() { // Initialize with ComponentTwo's initial value this.input_two = this.$refs.componentTwo.input_two; }, watch: { // Keep input_two in sync when ComponentTwo's value changes '$refs.componentTwo.input_two'(newValue) { this.input_two = newValue; } } } </script>
Update ComponentTwo.vue (fix the typo):
<template> <div> <input type="text" v-model="input_two"> </div> </template> <script> export default { name: "component-two", data() { return { input_two: 'Hello from ComponentTwo' // Fixed typo here } } } </script>
2. Use $emit for Child-to-Parent Communication (Recommended for Forms)
This follows Vue's one-way data flow and is ideal for form components where you need real-time sync. We'll use Vue's .sync modifier to simplify the syntax.
Update ComponentTwo.vue:
We'll make the child accept a prop and emit updates when the input changes:
<template> <div> <!-- Bind to the prop, emit update event on input --> <input type="text" :value="inputTwo" @input="$emit('update:inputTwo', $event.target.value)"> </div> </template> <script> export default { name: "component-two", // Define the prop to receive initial value from parent props: { inputTwo: { type: String, default: 'Hello from ComponentTwo' } } } </script>
Update ComponentOne.vue:
Use the .sync modifier to automatically sync the child's emitted value to your parent data:
<template> <div> <input type="text" v-model="input_one"> <!-- Use .sync to sync input_two with the child's inputTwo prop --> <component-two :inputTwo.sync="input_two"></component-two> </div> </template> <script> import ComponentTwo from 'component-two.vue' export default { name: "component-one", components: { ComponentTwo }, data() { return { input_one: 'Hello from ComponentOne', input_two: '' // Will be updated with child's value automatically } } } </script>
Now whenever the input in ComponentTwo changes, input_two in ComponentOne updates instantly—clean and maintainable!
3. Use Vuex for Complex State Management (Large Forms/Multiple Components)
If your registration form has many components that need to share state, Vuex is the way to go. It centralizes your form data so any component can access or update it.
Step 1: Set up Vuex
Create a store.js file:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { formData: { input_one: 'Hello from ComponentOne', input_two: 'Hello from ComponentTwo' } }, mutations: { // Mutation to update form data UPDATE_FORM_DATA(state, payload) { state.formData = { ...state.formData, ...payload } } } })
Don't forget to register the store in your main Vue instance:
import Vue from 'vue' import App from './App.vue' import store from './store' new Vue({ store, render: h => h(App) }).$mount('#app')
Step 2: Update ComponentOne.vue
Use mapState to access the store and bind your input to the state:
<template> <div> <input type="text" v-model="input_one"> <component-two></component-two> </div> </template> <script> import { mapState } from 'vuex' import ComponentTwo from 'component-two.vue' export default { name: "component-one", components: { ComponentTwo }, computed: { ...mapState(['formData']), input_one: { get() { return this.formData.input_one }, set(value) { this.$store.commit('UPDATE_FORM_DATA', { input_one: value }) } } } } </script>
Step 3: Update ComponentTwo.vue
Similarly, bind the input to the Vuex state:
<template> <div> <input type="text" v-model="input_two"> </div> </template> <script> import { mapState } from 'vuex' export default { name: "component-two", computed: { ...mapState(['formData']), input_two: { get() { return this.formData.input_two }, set(value) { this.$store.commit('UPDATE_FORM_DATA', { input_two: value }) } } } } </script>
Now all your form components share the same centralized state—perfect for large, complex forms!
Which Should You Choose?
- Use
refif you only need to read the child's data once (not recommended for real-time sync). - Use
$emit + .syncfor most form scenarios—it's simple, follows Vue's best practices, and works great for parent-child pairs. - Use Vuex if your form has many components or you need to share state across multiple parts of your app.
内容的提问来源于stack exchange,提问作者koddr

