vue中的 v-bind="$attrs" v-on="$listeners"个人见解

10,522 阅读1分钟

v-bind="$attrs" v-on="$listeners" 的作用:当vue中有多层组件嵌套, 且多层组件间需要相互传递数据时

image.png 如上图所示:

  • A组件嵌套B组件, B组件嵌套C组件
  • A 与 C 之间需要跨组件通信

A组件

<template>
  <div>
     <B :a="a" :b="b" @changeData="changeData" @another="another"></B>
  </div>
</template>

<script>
  import B from './B.vue'
  export default {
    name: 'A',
    components: {
      B
    },
    data () {
      return {
        a: 'a',
        b: 'b'
      }
    },
    methods: {
      changeData (params) {
         this.a = params
      },
      another () {
        alert(2)
      }
    }
  }
</script>


B组件

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

<script>
  import C from './C.vue'
  export default {
    name: 'B',
    components: {
      C
    },
    props: {
     a: String
    },
    data () {
      return {
      }
    },
    created () {
       console.log('this.$attrs', this.$attrs) 
       // b: b   this.$attrs 只会输出不在props中传递的属性
    },
    methods: {
    }
  }
</script>

对于子组件 要想真正实现多组件间相互传递 一般要在组件上加上inheritAttrs: false。 inheritAttrs: false可理解为:子组件props中并没有接受b设置选项 inheritAttrs: false,同样也不会作为根元素的属性节点。 没有被接收的数据都被 $attr 实例属性给接收,里面包含着所有父组件传递给子组件并没有在 Props里显示接收的数据

v-bind="$attrs" 可以继续向下传输。 只会输出不在props中传递的属性

C组件

<template>
  <div>
    <button @click='$listeners.changeData("gg")'>改变数组</button>
    <button @click='handleOther'>其他</button>
  </div>
</template>

<script>
  export default {
    name: 'C',
    data () {
      return {
      }
    },
    created () {
       console.log('this.$attrs', this.$attrs)
       // a: a,
       // b: b
    },
    methods: {
      handleOther () {
         this.$listeners.another()
      }
    }
  }
</script>

B组件没有对A组件的事件做任何处理而是通过v-on="$listeners"向下传给给了C组件

v-on="$listeners 可在html上直接触发, 也可在js中调用触发