Vue组件通信: provide + inject 模式和 props + custom events 模式

默认情况下都应该使用 props & customs 进行通信。 兄弟或者说邻居之间无法直接通信,只能通过共同的parent组件间接通信。

但是假定如果若干组件之间有若干级 parent -> child -> grandchild -> great-grandchild … 的关系,parent 需要传递属性给 great-grandchild,需要处理 great-grandchild 发出的自定义事件,虽然中间的若干组件 child, grandchild 等与这些属性或事件并无关系,但仍然需要传递。
为了避免过多的层层传递,Vue 提供了 provide - inject 的通信模式以实现code 简化。
在parent 级的组件上 provide 需要的数据或者方法,然后这个组件的child, grandchild, great-grandchild 组件等都可以通过 inject 使用这些数据或方法,两个组件之间只要满足类似于parent - child 的关系就行,邻居关系的组件除外。

如果在所有的情况下都使用 props & custom events 进行组件之间的通信并不是错误的做法,使用 provide - inject 模式进行通信是一种可选做法,合理使用在某些情况下可以使代码更简洁。

举例:

  1. parent 组件 App.vue, provide 对象数组 topics, 以及方法activateTopic
<template>
  <div>
    <knowledge-base></knowledge-base>
  </div>
</template>

<script>
export default {
  data() {
    return {
      topics: [
        {
          id: 'basics',
          title: 'The Basics',
          description: 'Core Vue basics you have to know',
          fullText:
            'Vue is a great framework',
        },
      ],
      activeTopic: null,
    };
  },

  // 如果写成   provide: { topics: [{}] }
  // 就需要copy一遍data里的topics数组,
  // 这样会造成代码重复,所以改成 provide() {} 
  // 即方法的形式
  provide() {
    return {
      topics: this.topics,
      // not executing, just pointing to it
      // selectTopic1 是任意指定的名称
      selectTopic1: this.activateTopic,
    }
  },

  methods: {
    activateTopic(topicId) {
      this.activeTopic = this.topics.find((topic) => topic.id === topicId);
    },
  },
};
</script>
  1. child 组件 knowledgeBase.vue, 由于自己并不需要使用其他组件的数据和方法,而且由于app 使用了 provide - inject 模式, 因此不需要传递数据或事件,没有props, 也没有emits,十分简洁。反之,如果不使用 provide + inject ,代码不会这么简洁。
<template>
  <section>
    <h2>Select a Topic</h2>
    <knowledge-grid></knowledge-grid>
  </section>
</template>

<script>
export default {
};
</script>
  1. grandchild 组件 knowledgeGrid.vue,通过inject使用在App.vue 组件中提供的topics数组。
<template>
  <ul>
    <knowledge-element
      v-for="topic in topics"
      :key="topic.id"
      :id="topic.id"
      :topic-name="topic.title"
      :description="topic.description"
    ></knowledge-element>
  </ul>
</template>

<script>
export default {
  inject: ['topics'],
};
</script>
  1. great-grandchild 组件 KnowledgeElement.vue,使用inject,当 click 事件发生时,App.vue 中对应的方法会被调用。
<template>
  <li>
    <h3>{{ topicName }}</h3>
    <p>{{ description }}</p>
    <button @click="selectTopic1(id)">Learn More</button>
  </li>
</template>

<script>
export default {
  // selectTopic1 这里是随意定的一个名称
  inject:['selectTopic1'],
  props: ['id', 'topicName', 'description'],
};
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值