面试题:Vue 组件之间的通信方式有哪些?

在 Vue 中,组件之间的通信是开发复杂应用的关键。根据组件之间的关系(父子组件、兄弟组件、跨级组件等),可以选择不同的通信方式。以下是 Vue 组件之间常见的通信方式:


1. 父子组件通信

(1)父组件向子组件传递数据:props

  • 父组件通过 props 向子组件传递数据。
  • 子组件通过 props 接收数据。

父组件:

<template>
  <ChildComponent :message="parentMessage" />
</template>

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

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

子组件:

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

<script>
export default {
  props: {
    message: String,
  },
};
</script>

(2)子组件向父组件传递数据:$emit

  • 子组件通过 $emit 触发自定义事件,向父组件传递数据。
  • 父组件通过 v-on 监听事件并处理数据。

子组件:

<template>
  <button @click="sendMessage">发送消息</button>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$emit('message-from-child', 'Hello from Child');
    },
  },
};
</script>

父组件:

<template>
  <ChildComponent @message-from-child="handleMessage" />
</template>

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

export default {
  components: { ChildComponent },
  methods: {
    handleMessage(message) {
      console.log(message); // 输出: Hello from Child
    },
  },
};
</script>

2. 兄弟组件通信

(1)通过共同的父组件

  • 兄弟组件可以通过共同的父组件作为中介进行通信。
  • 父组件通过 props$emit 实现数据传递。

父组件:

<template>
  <ChildA :message="message" @update-message="updateMessage" />
  <ChildB :message="message" />
</template>

<script>
import ChildA from './ChildA.vue';
import ChildB from './ChildB.vue';

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

ChildA:

<template>
  <button @click="sendMessage">更新消息</button>
</template>

<script>
export default {
  props: ['message'],
  methods: {
    sendMessage() {
      this.$emit('update-message', 'Updated Message');
    },
  },
};
</script>

ChildB:

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

<script>
export default {
  props: ['message'],
};
</script>

(2)使用事件总线(Event Bus)

  • 创建一个 Vue 实例作为事件总线,用于兄弟组件之间的通信。
  • 组件通过 $on 监听事件,通过 $emit 触发事件。

Event Bus:

// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();

ChildA:

<template>
  <button @click="sendMessage">发送消息</button>
</template>

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

export default {
  methods: {
    sendMessage() {
      EventBus.$emit('message-from-a', 'Hello from ChildA');
    },
  },
};
</script>

ChildB:

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

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

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

3. 跨级组件通信

(1)使用 provideinject

  • 祖先组件通过 provide 提供数据。
  • 后代组件通过 inject 注入数据。

祖先组件:

<template>
  <ChildComponent />
</template>

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

后代组件:

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

<script>
export default {
  inject: ['message'],
};
</script>

(2)使用 Vuex

  • Vuex 是 Vue 的官方状态管理库,适用于跨级组件或复杂应用的通信。
  • 组件通过 mapStatemapGettersmapActions 等辅助函数访问和修改全局状态。

Vuex Store:

// 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;
    },
  },
  actions: {
    updateMessage({ commit }, newMessage) {
      commit('updateMessage', newMessage);
    },
  },
});

组件 A:

<template>
  <button @click="updateMessage">更新消息</button>
</template>

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

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

组件 B:

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

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

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

4. 其他通信方式

(1)$refs

  • 通过 ref 属性获取子组件的实例,直接调用子组件的方法或访问数据。

父组件:

<template>
  <ChildComponent ref="child" />
  <button @click="callChildMethod">调用子组件方法</button>
</template>

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

export default {
  components: { ChildComponent },
  methods: {
    callChildMethod() {
      this.$refs.child.childMethod();
    },
  },
};
</script>

子组件:

<script>
export default {
  methods: {
    childMethod() {
      console.log('子组件方法被调用');
    },
  },
};
</script>

(2)$parent$children

  • 通过 $parent 访问父组件实例。
  • 通过 $children 访问子组件实例。

注意:这种方式耦合性较高,不推荐使用。


总结

Vue 组件之间的通信方式包括:

  1. 父子组件props$emit
  2. 兄弟组件:通过共同的父组件或事件总线。
  3. 跨级组件provideinject,或使用 Vuex。
  4. 其他方式$refs$parent$children

根据组件之间的关系和具体需求,选择合适的通信方式,可以提高代码的可维护性和可读性。

THE END
点赞14 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容