VUE3多层组件传值(复杂场景)provide/inject

单纯使用 provideinject 机制只能实现祖父组件向孙组件传递数据,而无法实现孙组件向祖父组件传递数据。如果需要实现双向通信,可以结合 provideinject 与事件机制或状态管理库来完成。

以下是几种解决方案:

1. 使用 provideinject 结合回调函数

祖父组件提供一个回调函数,孙组件调用这个回调函数将数据传递回祖父组件。

代码示例:

祖父组件 (Grandparent.vue)

<template>
  <div>
    <Parent />
  </div>
</template>
​
<script>
import { provide, ref } from 'vue';
import Parent from './Parent.vue';
​
export default {
  components: { Parent },
  setup() {
    const sharedData = ref('Hello from Grandparent');
    const receiveFromGrandchild = (message) => {
      console.log('Received from Grandchild:', message);
      sharedData.value = message;
    };
​
    provide('sharedData', sharedData);
    provide('sendToGrandparent', receiveFromGrandchild);
  }
};
</script>

父组件 (Parent.vue)

<template>
  <div>
    <Child />
  </div>
</template>
​
<script>
import Child from './Child.vue';
​
export default {
  components: { Child }
};
</script>

子组件 (Child.vue)

<template>
  <div>
    <Grandchild />
  </div>
</template>
​
<script>
import Grandchild from './Grandchild.vue';
​
export default {
  components: { Grandchild }
};
</script>

孙组件 (Grandchild.vue)

<template>
  <div>
    <button @click="sendMessageToGrandparent">Send to Grandparent</button>
  </div>
</template>
​
<script>
import { inject } from 'vue';
​
export default {
  setup() {
    const sendToGrandparent = inject('sendToGrandparent');
​
    const sendMessageToGrandparent = () => {
      sendToGrandparent('Hello from Grandchild');
    };
​
    return {
      sendMessageToGrandparent
    };
  }
};
</script>

2. 使用 Vuex(状态管理库)

对于更复杂的场景,可以使用 Vuex 来管理全局状态,实现任意组件之间的数据共享和方法调用。

代码示例:

store.js

import { createStore } from 'vuex';
​
export default createStore({
  state: {
    sharedData: 'Hello from Grandparent'
  },
  mutations: {
    setSharedData(state, newData) {
      state.sharedData = newData;
    }
  },
  actions: {
    updateSharedData({ commit }, newData) {
      commit('setSharedData', newData);
    }
  },
  getters: {
    sharedData: (state) => state.sharedData
  }
});

祖父组件 (Grandparent.vue)

<template>
  <div>
    <Parent />
  </div>
</template>
​
<script>
import { computed } from 'vue';
import { useStore } from 'vuex';
import Parent from './Parent.vue';
​
export default {
  components: { Parent },
  setup() {
    const store = useStore();
    const sharedData = computed(() => store.getters.sharedData);
​
    return {
      sharedData
    };
  }
};
</script>

孙组件 (Grandchild.vue)

<template>
  <div>
    <button @click="sendMessageToGrandparent">Send to Grandparent</button>
  </div>
</template>
​
<script>
import { useStore } from 'vuex';
​
export default {
  setup() {
    const store = useStore();
​
    const sendMessageToGrandparent = () => {
      store.dispatch('updateSharedData', 'Hello from Grandchild');
    };
​
    return {
      sendMessageToGrandparent
    };
  }
};
</script>

3. 使用 EventBus

使用事件总线 (EventBus) 也是一种常见的解决方案。可以通过创建一个独立的事件总线实例,在需要的组件中引入并进行事件的监听和触发。

代码示例:

EventBus.js

import mitt from 'mitt';
const emitter = mitt();
export default emitter;

祖父组件 (Grandparent.vue)

<template>
  <div>
    <Parent />
  </div>
</template>
​
<script>
import emitter from './EventBus';
import Parent from './Parent.vue';
​
export default {
  components: { Parent },
  mounted() {
    emitter.on('messageFromGrandchild', this.handleMessageFromGrandchild);
  },
  methods: {
    handleMessageFromGrandchild(message) {
      console.log('Received from Grandchild:', message);
    }
  },
  beforeUnmount() {
    emitter.off('messageFromGrandchild', this.handleMessageFromGrandchild);
  }
};
</script>

孙组件 (Grandchild.vue)

<template>
  <div>
    <button @click="sendMessageToGrandparent">Send to Grandparent</button>
  </div>
</template>
​
<script>
import emitter from './EventBus';
​
export default {
  methods: {
    sendMessageToGrandparent() {
      emitter.emit('messageFromGrandchild', 'Hello from Grandchild');
    }
  }
};
</script>

这些方法各有优劣,具体选择哪一种方法可以根据项目的复杂度和需求来决定。对于简单的场景,使用 provideinject 结合回调函数可能是最简单的解决方案;而对于复杂的全局状态管理,Vuex 会更加合适。使用 EventBus 则适用于需要频繁跨组件通信但不想引入全局状态管理库的情况。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值