Vue属性 inheritAttrs、$attrs和$listeners初窥

inheritAttrs

inheritAttrs在Vue官方文档上面的解释如下:
在这里插入图片描述
起初对于官方的定义不胜理解,写了一个demo之后才有了初步理解:
inheritAttrs 默认true状态时,当父组件在子组件引用标签上 传入一个子组件未定义(props中未定义)的属性,会将该属性添加到子组件的根节点上(变成一个自定义属性)这也解释了~ 默认状态下,给子组件引用标签上面直接添加 id class 。可以直接将这两个属性添加到子组件的根节点上~~
改为false时就会忽略这些未定义的属性 (class 和 style不受 false的影响

让我们来看一个示例:

helloWorld.vue是父组件:

<template>
  <div class="hello">
    <h3>测试 inheritAttrs、$attrs、 $listeners</h3>
    <child1 :text1="msg1" :text2="msg2" class="father" id="child" data-test="test"></child1>
  </div>
</template>

<script>
import Child1 from './child1'
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg1: '传入子组件的文字',
      msg2: '传入二级子组件的文字'
    }
  },
  components: {
    Child1
  },

child1.vue 为子组件:

<template>
  <div class="child1-test">
    <h3 @click="event1">{{text1}}</h3>
    <child2 v-bind="$attrs" v-on="$listeners"></child2>
  </div>
</template>
<script>
import Child2 from './child2'
export default {
  name: 'child1',
  props: {
    text1: {
      type: String,
      default: ''
    }
  },
  inheritAttrs: true,

这两段Vue组件中,在父组件的对子组件的引用中,除了传入了子组件中props定义的text1, text2、data-test、class、id都是未定义;此时子组件的inheritAttrs设置为true(默认即为true,此处写出来以便观察)。
查看页面中DOM结构如下:
在这里插入图片描述
如图所示,未定义的几个属性,都跑到子组件的根节点 div.child1-test 上面去了。
此时我们再将inheritAttrs属性设置为false观察:
在这里插入图片描述
除了class 依然被添加到子组件的根节点上面,其他属性都被忽略。

$attrs 和 $listeners

官方文档解释如下:
在这里插入图片描述

通俗的来讲:$attrs 是传入子组件中的自定义属性的对象(不包括子组件已定义的props 和 class、style属性);
依旧以上面代码为例,在子组件的生命周期mounted函数中,我们console.log一下 $attrs 此时控制台显示的内容如下:
在这里插入图片描述

然而$ l i s t e n e r s 就 是 可 以 通 过 listeners就是可以通过 listenerslisteners向更深层次的组件传递事件。比如说三层组件的嵌套;如果子子组件想要将事件传递到父级,通常我们的写法是先将事件传递到子组件中,然后再通过子组件将事件传递到父组件。这样的写法,费时费力,修改困难。而通过$listeners就可以更加省力;
依旧是上面的示例,我们添加一个子子组件child2.vue。然后添加事件:
父组件:

<template>
  <div class="hello">
    <h3>测试 inheritAttrs、$attrs、 $listeners</h3>
    <child1
      :text1="msg1"
      :text2="msg2"
      class="father"
      id="child"
      data-test="test"
      @event1="event1"
      @event2="event2"
    ></child1>
  </div>
</template>

<script>
import Child1 from './child1'
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg1: '传入子组件的文字',
      msg2: '传入二级子组件的文字'
    }
  },
  components: {
    Child1
  },
  methods: {
    event1 (val) {
      console.log(val)
    },
    event2 (val) {
      console.log(val)
    }
  }
}
</script>

子组件:

<template>
  <div class="child1-test">
    <h3 @click="event1">{{text1}}</h3>
    <child2 v-bind="$attrs" v-on="$listeners"></child2>
  </div>
</template>
<script>
import Child2 from './child2'
export default {
  name: 'child1',
  props: {
    text1: {
      type: String,
      default: ''
    }
  },
  inheritAttrs: false,
  mounted () {
    console.log(this.$attrs)
  },
  components: {
    Child2
  },
  methods: {
    event1 () {
      this.$emit('event1', '这是一级子组件点击事件')
    }
  }
}
</script>

子子组件:

<template>
  <div>
    <h3 @click.stop="event2">{{text2}}</h3>
  </div>
</template>
<script>
export default {
  name: 'child2',
  props: {
    text2: {
      type: String,
      default: ''
    }
  },
  mounted () {
    console.log(this.$attrs)
  },
  methods: {
    event2 () {
      this.$emit('event2', '二级子页面点击')
    }
  }
}
</script>

我们在子组件中使用v-on="$listeners"去传递事件。此时在页面中分别点击两个子组件中的文字,控制台效果:
在这里插入图片描述

补充: 用 v-bind="$attrs" 可以将父级自定义的属性对象 直接传入内部组件,这样的方式非常有用。

总结

Vue2.4 新增的这三个属性都非常的实用,对于结果共用组件封装,多层次组件嵌套上面,有非常大的帮助,本人也在持续学习中,对于某些知识理解尚且不足,希望在后续的学习中补充更多的实用场景。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值