vue组件传值之$attrs、$listeners

组件传值总结

  1. props和emit:父子组件传值
  2. provide和inject:父子组件或者爷孙组件传值
  3. $parent,$root,$chidren:父子组件传值
  4. vuex
  5. 事件总线(vue实例)
  6. ref/$refs
  7. $attrs、$listeners:父子组件传值
    前6种可能大部人都知道,这篇文章主要对$attrs、$listener进行一个介绍。

$attrs、$listeners

$attrs:

官方文档介绍:包含了父作用域不作为prop被识别(且获取)的attribute绑定(class和style除外)。当一个组件没有生命任何prop时,这里会包含所有父作用域的绑定(class和style除外),并且可以通过v-bind="$attrs"传入内部组件–在创建高级别的组件时非常有用。

通俗地来说就是如果从父组件传过来的值,没有在子组件中被接收,那么这些值就会被存在$attrs对象中。

下面这个例子中有Father、Son、GrandSon三个组件。

//Father.vue
<template>
  <div class="father">
    <span>父亲</span>
    <Son :message="message" :age="18"></Son>
  </div>
</template>

<script>
import Son from "../components/Son.vue";
export default {
  data() {
    return {
      message: "父组件传过来的值",
      age: 18,
    };
  },
  components: {
    Son,
  },
};
</script>

<style>
</style>


//Son.vue
<template>
  <div class="son">
    <span>儿子</span>
    <GrandSon v-bind="$attrs"></GrandSon>
  </div>
</template>

<script>
import GrandSon from "../components/GrandSon.vue";
export default {
  components: {
    GrandSon,
  },
  created() {
    console.log("son", this.$attrs);
  },
};



//GrandSon.vue
<template>
  <div class="grandson">
    <span>孙子</span>
    <div>{{ $attrs.message }}</div>
  </div>
</template>

<script>
export default {
  created() {
    console.log("grandson", this.$attrs);
  },
};
</script>

<style>
</style>
</script>

<style>
</style>

vue组件传值之$attrs、$listeners_第1张图片
可以看到无论是在Son组件中还是GrandSon组件中都可以拿到$attrs中的值。

当我们对Son组件进行改变时,

//Son.vue
<template>
  <div class="son">
    <span>儿子</span>
    <GrandSon v-bind="$attrs"></GrandSon>
  </div>
</template>

<script>
import GrandSon from "../components/GrandSon.vue";
export default {
  components: {
    GrandSon,
  },
  props: {
    message: String,
  },
  created() {
    console.log("son", this.$attrs);
  },
};
</script>

<style>
</style>

vue组件传值之$attrs、$listeners_第2张图片
当我们在Son组件中使用props去接收GrandSon发送过来中的值的时候,该值就不会被带到$attrs对象中去,没有被props接收的值还是会被带到$attrs对象中去。

$listeners

包含了父作用域中的(不包含.native修饰器的)v-on事件监听器。它可以通过v-on="$listeners"传入内部组件–在创建更高层次的组件时非常有用。

通俗地来说就是可以从孙子组件发送事件到父子组件中。

//Father.vue
<template>
  <div class="father">
    <span>父亲</span>
    <Son @event="event"></Son>
  </div>
</template>

<script>
import Son from "../components/Son.vue";
export default {
  components: {
    Son,
  },
  methods: {
    event() {
      console.log("从GrandSon组件发送过来的数据");
    },
  },
};
</script>

<style>
</style>


//Son.vue
<template>
  <div class="son">
    <span>儿子</span>
    <GrandSon v-on="$listeners"></GrandSon>
  </div>
</template>

<script>
import GrandSon from "../components/GrandSon.vue";
export default {
  components: {
    GrandSon,
  },
};
</script>

<style>
</style>


//GrandSon.vue
<template>
  <div class="grandson">
    <span>孙子</span>
    <button @click="click">发送事件</button>
  </div>
</template>

<script>
export default {
  methods: {
    click() {
      this.$emit("event");
    },
  },
};
</script>

<style>
</style>

vue组件传值之$attrs、$listeners_第3张图片

普通的emit只能从子组件传到父组件,通过$listeners,我们可以实现从孙子组件把事件传到父子组件,不需要通过emit逐层传递。

$attrs和$listeners主要用来父孙组件之间传值,有的同学说也可以用provide和inject来实现父孙组件之间传值,但需要注意的是provide和inject只能从父组件向孙组件传值,不能从孙组件向父组件传值,这种情况就需要使用$attrs和$listeners来实现了。

你可能感兴趣的:(vue,vue.js,javascript,前端)