vue 的五种组件通信方式

props / emit

原理

父组件通过 props 向子组件传递数据,子组件通过 emit 发送事件给父组件。

应用场景

适用于父子组件之间的简单通信,父组件向子组件传递数据,子组件通过事件触发通知父组件。

示例代码

父组件:

<template>
  <div>
    <!-- 子组件 -->
    <ChildComponent @notify="handleNotify"></ChildComponent>
  </div>
</template>

<script>
import { defineComponent } from "vue";
import ChildComponent from './ChildComponent.vue';

export default defineComponent({
  name: "父组件名",
  components: {
    ChildComponent
  },
  setup() {
    const state = reactive({});

    const handleNotify = (message) => {
      console.log('从子组件接收到:', message);
    }

    return {
      ...toRefs(state),
      handleNotify,
    };
  },
});
</script>

子组件:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="notifyParent">通知父组件</button>
  </div>
</template>
  
<script>
import { defineComponent } from "vue";

export default defineComponent({
  name: "子组件名",
  props: {
    message: {
      type: String,
      default: "",
    },
  },
  setup(props, { emit }) {
    const state = reactive({});
    
    const notifyParent = () => {
      // 在父组件调用 notify 方法获取传的值
      emit("notify", "子组件发送的消息" + props.message);
    };

    return {
      ...toRefs(state),
      notifyParent,
    };
  },
});
</script>

Event Bus

事件总线(全局Vue实例)

原理

Vue 实例作为中央事件总线,通过 $on 监听事件,$emit 发布事件,实现任意组件间的通信。

应用场景

适用于跨越多层级关系的非父子组件通信,或者兄弟组件之间的通信。

示例代码

// main.js 或其他中心位置

import { createApp } from 'vue';
import App from './App.vue';

export const app = createApp(App);
export const eventBus = app.config.globalProperties.$eventBus = new app.config.globalProperties.Vue();

// 组件A 传递
eventBus.$emit('event-name', data);

// 组件B 接收
eventBus.$on('event-name', data => {
  // 处理事件数据
});

Vuex

原理

Vue.js 的官方状态管理库,集中式存储管理应用的所有组件的状态。

应用场景

适用于大型单页应用中,多个组件需要共享状态或需要对状态进行复杂的管理操作

示例代码

Vuex 状态管理:

// store/index.js

import { createStore } from 'vuex';

export default createStore({
  state() {
    return {
      count: 0
    };
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  },
  getters: {
    getCount: state => state.count
  }
});

在组件中使用 Vuex:

<template>
  <div>
    <p>计数:{{ count }}</p>
    <button @click="increment">增加</button>
  </div>
</template>
  
<script>
import { defineComponent, computed } from "vue";
import { useStore } from "vuex";

export default defineComponent({
  setup() {
    const store = useStore();
    const count = computed(() => store.state.count);

    const increment = () => {
      store.commit("increment");
    };

    return {
      count,
      increment,
    };
  },
});
</script>

Provide / Inject

原理

祖先组件通过 provide 提供数据,后代组件通过 inject 注入数据,实现祖先与后代之间的跨层级通信。

应用场景

适用于复杂的组件结构,需要在多层嵌套的组件中传递数据。

示例代码

祖先组件传递数据:

<script>
import { defineComponent, provide } from "vue";

export default defineComponent({
  setup() {
    provide('theme', 'dark');
  },
});
</script>

后代组件接收数据:

<template>
  <div>
    <p>主题:{{ theme }}</p>
  </div>
</template>
  
<script>
import { defineComponent, inject } from "vue";

export default defineComponent({
  setup() {
    const theme = inject('theme');
    return { theme };
  },
});
</script>

$attrs / $listeners

原理

子组件可以通过 $attrs 获取父组件传递的非 prop 特性,通过 $listeners 获取父组件传递的事件监听器。

应用场景

适用于需要在子组件中访问父组件的特性和监听器的场景。

示例代码

父组件:

<template>
  <div>
    <ChildComponent v-bind="$attrs" v-on="$listeners"></ChildComponent>
  </div>
</template>

子组件:

<template>
  <div>
    <input type="text" v-bind="$attrs" v-on="$listeners">
    <button @click="$emit('click')">点击</button>
  </div>
</template>
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值