Vue基础之组件通信(3)provide和inject、$ attrs和$ listeners

provide 和 inject

官方释义这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

  • 使用
    在祖先组件使用provide向下注入依赖,在所有的子孙组件可以使用inject接收到传输的数据。
  • 示例
    祖先组件
<template>
  <div class="grandfather">
    祖先组件
    <father></father>
  </div>
</template>
<script>
import father from "./father";
export default {
  provide: {
    grandFtext: "一段来自祖先组件的数据"
  }
};
</script>

注入
父组件

<template>
  <div class="father">
    父组件
    <p>{{ text }}</p>
    <son></son>
  </div>
</template>
<script>
export default {
  inject: ["grandFtext"],
  data() {
    return {
      text: this.grandFtext
    };
  }
};
</script>

子组件

<template>
  <div class="son">
    子组件
    <p>{{ text }}</p>
  </div>
</template>
<script>
export default {
  inject: ["grandFtext"],
  data() {
    return {
      text: this.grandFtext
    };
  },
};
</script>
  • 效果
    Vue基础之组件通信(3)provide和inject、$ attrs和$ listeners_第1张图片

$ attrs和$ listeners

上述的provide和inject实现了多层级组件数据的传输,但是不能够实现子组件向祖先组件传递数据,如果要实现子传祖,可以使用$ attrs和$ listeners

官方释义:$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。 $listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
其实很好理解,也就是从父组件定义并且没有在组件中用props接收的prop,都会在$attrs中,可以将其传入子孙组件并使用,而 $listeners则包括了在父组件上的所有v-on事件监听器,将其传入子孙组件,就可以使用 $emit的方式向祖先组件传送数据。

  • 示例
    祖先组件
<template>
  <div class="grandfather">
    祖先组件
    <p>{{ text }}</p> //显示子孙组件传过来的值用
    <father
      name="爷爷"
      text="一段来自祖先组件的数据" //这一段文字稍后在父组件是没有被props接收的
      @showSon="showSon"
    ></father>
  </div>
</template>

<script>
export default {
  data() {
    return {
      text: null
    };
  },
  methods: {
    showSon(data) {//接收子孙组件传来的数据
      this.text = data; 
    }
  }
};
</script>

父组件

<template>
  <div class="father">
    父组件
    <p></p>
    <son v-bind="$attrs" v-on="$listeners"></son>
    //由于props只接受了name,所以另一个prop会在$attrs中,可以传到子组件。
    //这里$listeners就包括了祖先组件定义在父组件上的事件监听@showson,传入子组件。
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props: {
    name: {
      default: ""
    }
  },
};
</script>

子组件:

<template>
  <div class="son">
    子组件
    <p>{{ text }}</p>
    <button @click="clickEvent">向祖先传值</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      text: this.$attrs.text //使用来自祖先组件的数据
    };
  },
  methods: {
    clickEvent() {
      this.$emit("showSon", "一段来自子组件的数据");
      //可以使用定义在父组件上的事件监听
    }
  }
};
</script>
  • 效果
    Vue基础之组件通信(3)provide和inject、$ attrs和$ listeners_第2张图片
    可以看到是可以使用到祖先组件传输的数据的。
    点击子组件的按钮后:
    Vue基础之组件通信(3)provide和inject、$ attrs和$ listeners_第3张图片
    祖先组件拿到了来自子组件的数据。
  • 小结
    这两种方式虽然不常用,但是还是有认识的必要,因为相对比 eventBus和Vuex,会更加方便些。

你可能感兴趣的:(vue,vue)