vue2父子组件通信

 前端   打工人   2024-09-15 11:25   21
  Vue

在 Vue 2 中,父子组件之间的通信是一个常见的需求,特别是在子组件需要修改父组件的属性时。Vue 2 提供了几种方案来实现这一目标。以下是 Vue 2 中父子组件通信的所有常见方案:

1. 使用 props$emit

这是 Vue 中最基础的组件通信方式,特别适合子组件向父组件传递信息或请求修改父组件的状态。

步骤:

  1. 父组件子组件传递数据(通过 props)。
  2. 子组件通过 $emit父组件发送事件,以便通知父组件修改数据。

示例:

父组件:

<template>
  <div>
    <ChildComponent :message="parentMessage" @updateMessage="updateMessage"/>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return {
      parentMessage: 'Hello from Parent'
    };
  },
  methods: {
    updateMessage(newMessage) {
      this.parentMessage = newMessage;
    }
  }
};
</script>

子组件:

<template>
  <div>
    <button @click="sendUpdate">Update Parent Message</button>
  </div>
</template>

<script>
export default {
  props: ['message'],
  methods: {
    sendUpdate() {
      this.$emit('updateMessage', 'Message Updated from Child');
    }
  }
};
</script>

2. 使用 v-model 自定义事件

v-model 是 Vue 2 提供的语法糖,用于在父组件和子组件之间进行双向绑定。你可以自定义 v-model 的事件和属性来实现子组件向父组件传递数据。

步骤:

  1. 在子组件中,定义 model 选项来指定 v-model 使用的事件和属性。
  2. 在父组件中使用 v-model 来双向绑定数据。

示例:

父组件:

<template>
  <div>
    <ChildComponent v-model="parentMessage"/>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return {
      parentMessage: 'Hello from Parent'
    };
  }
};
</script>

子组件:

<template>
  <div>
    <button @click="updateParent">Update Parent Message</button>
  </div>
</template>

<script>
export default {
  props: {
    value: String
  },
  methods: {
    updateParent() {
      this.$emit('input', 'Message Updated from Child');
    }
  }
};
</script>

3. 使用事件总线(Event Bus)

事件总线是一种跨组件通信的模式。通过创建一个中央事件总线,子组件可以触发事件,而父组件可以监听这些事件。注意:这种方法在 Vue 3 中被不推荐使用,但在 Vue 2 中仍然有效。

步骤:

  1. 创建一个事件总线实例。
  2. 在子组件中触发事件。
  3. 在父组件中监听事件。

示例:

eventBus.js:

import Vue from 'vue';
export const EventBus = new Vue();

父组件:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { EventBus } from './eventBus';

export default {
  data() {
    return {
      message: 'Hello from Parent'
    };
  },
  created() {
    EventBus.$on('updateMessage', (newMessage) => {
      this.message = newMessage;
    });
  }
};
</script>

子组件:

<template>
  <div>
    <button @click="updateParent">Update Parent Message</button>
  </div>
</template>

<script>
import { EventBus } from './eventBus';

export default {
  methods: {
    updateParent() {
      EventBus.$emit('updateMessage', 'Message Updated from Child');
    }
  }
};
</script>

4. 使用 Vuex(状态管理)

对于更复杂的应用,使用 Vuex 状态管理库来管理状态是一个好的选择。通过 Vuex,子组件可以通过 Vuex 的 actions 或 mutations 来修改全局状态,父组件则可以通过 computed 属性来响应这些变化。

步骤:

  1. 在 Vuex store 中定义状态和 mutations。
  2. 在父组件中通过 computed 属性访问状态。
  3. 在子组件中通过 Vuex actions 或 mutations 修改状态。

示例:

store.js:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    message: 'Hello from Vuex'
  },
  mutations: {
    updateMessage(state, newMessage) {
      state.message = newMessage;
    }
  }
});

父组件:

<template>
  <div>
    <p>{{ message }}</p>
    <ChildComponent/>
  </div>
</template>

<script>
import { mapState } from 'vuex';
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  computed: {
    ...mapState(['message'])
  }
};
</script>

子组件:

<template>
  <div>
    <button @click="updateParent">Update Parent Message</button>
  </div>
</template>

<script>
import { mapMutations } from 'vuex';

export default {
  methods: {
    ...mapMutations(['updateMessage']),
    updateParent() {
      this.updateMessage('Message Updated from Child');
    }
  }
};
</script>

5. 使用 Provide/Inject API

Vue 2 的 provideinject API 可以在祖先组件和后代组件之间传递数据。这对于需要在多个层级的组件之间传递数据的情况非常有用。

步骤:

  1. 在祖先组件中使用 provide 提供数据。
  2. 在后代组件中使用 inject 注入数据。

示例:

祖先组件:

<template>
  <div>
    <ChildComponent/>
  </div>
</template>

<script>
export default {
  provide() {
    return {
      message: 'Hello from Provide'
    };
  }
};
</script>

子组件:

<template>
  <div>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
export default {
  inject: ['message'],
  methods: {
    updateMessage() {
      console.log(this.message);
      // 你可以通过其他方式通知父组件
    }
  }
};
</script>

6. 使用自定义事件

除了 $emit,你还可以使用自定义事件来实现复杂的组件间通信。通常结合 v-model$emit 使用。

示例:

父组件:

<template>
  <div>
    <CustomComponent :value="parentValue" @updateValue="updateValue"/>
  </div>
</template>

<script>
import CustomComponent from './CustomComponent.vue';

export default {
  components: { CustomComponent },
  data() {
    return {
      parentValue: 'Initial Value'
    };
  },
  methods: {
    updateValue(newValue) {
      this.parentValue = newValue;
    }
  }
};
</script>

子组件:

<template>
  <div>
    <button @click="notifyParent">Change Value</button>
  </div>
</template>

<script>
export default {
  props: ['value'],
  methods: {
    notifyParent() {
      this.$emit('updateValue', 'New Value from Child');
    }
  }
};
</script>

这些方案提供了多种实现父子组件通信的方式。根据具体的需求和应用的复杂度,你可以选择最适合的方案来实现组件间的交互。