vue知识

一、$attrs内容

$attrs是什么?

包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=“$attrs” 传入内部组件——在创建高级别的组件时非常有用。

以上内容为,vue官方文档中对$attrs的介绍。一堆修饰限定、名词堆砌,对于新手来说可谓是极其不友好。

其实想要弄清楚$attrs到底是个什么东西,也很简单,先要了解几个概念。
1. attribute: 即html元素中所拥有的属性。

   	 <!-- 如id、title、onclick等,这些都属于attribute -->
   	 <div id="box" title="标题" onclick="fun()"></div>

2. 父组件: 组件化是vue中一个非常重要的概念,vue文件内能引用其他的vue文件作为组件使用,以此达到简化和复用代码的目的。一般我们将被引用的vue组件称为“子组件”,而引用“子组件”的页面,称之为父组件。

<!-- 我是组件Father.vue文件 -->
  <div>
    <son>我是子组件</son>
  </div>

3.父作用域: 理解了上面父组件的概念后,父作用域是什么就呼之欲出了。即父组件模板所在的作用域,即为父作用域,非常浅显易懂有没有。

拿父组件中的代码举例,父作用域的范围就是,Father.vue文件。

结合上方官方文档中的定义与上面的几个概念,我对$attrs做出的理解就是父组件中,未被子组件使用prop接收的那些属性(class 和 style 除外))

$attrs能做些什么?

根据官方文档的说法就是,(父组件中未被子组件接收的值)可以通过 v-bind=“$attrs” 传入内部组件,即传入子组件中的组件。也就是说,只要父组件传递的参数,没有被子组件或是子组件的内部组件,用prop所接收,那么就能实现父组件对任意后代组件进行传递参数的操作。

这是一个非常强大的功能。因为如果不依靠$attrs,来实现父组件对其子组件以外的后代组件,进行传参操作。
我所能想到的就只有vuex、事件总线、或是prop逐级进行接受传递等方法。与 $attrs对比来看,可谓是十分的繁琐、且不优雅。

$attrs使用方式

父组件

<template>
  <div>
    <div class="father">
      <span>父组件</span>
      <span>name:{{ name }}</span>
      <span>obj:{{ obj }}</span>
    </div>
    <son :id="id" :name="name" :age="age" :obj="obj"/>
  </div>
</template>

<script>
import Son from "./Son";

export default {
  name: "Father",
  components: {Son},
  data() {
    return {
      id: 001,
      name: 'Rise',
      age: 66,
      obj: {
        a: 1,
        b: 2
      }
    }
  }
}
</script>

子组件

<template>
  <div>
    <div class="son">
      <span>子组件</span>
    </div>
    <grandson v-bind="$attrs"/>

  </div>
</template>

<script>
import Grandson from "./Grandson";
export default {
  name: "Son",
  inheritAttrs:false,
  components: {Grandson},
  data(){
    return{}
  }
}
</script>

孙组件

<template>
  <div class="grandson">
    <div>孙组件</div>
    <span>name:{{name}}</span>
    <span>obj:{{obj}}</span>
  </div>
</template>

<script>
export default {
  name: "Grandson",
  inheritAttrs:false,
  props:{
    name:{type:String},
    obj:{type:Object}
  }
}
</script>

在这里插入图片描述

$attrs传参注意事项

1. 首先,$attrs所传递的参数为,子组件未接受的参数,所以如果参数在子组件内被使用prop接收过了,那么孙组件将无法在接收到。
在这里插入图片描述
2. 可以看到inheritAttrs属性,在上方的代码中出现。inheritAttrs是用来指定,$attrs中的值,是否在当前组件的根节点上显示,如果指定其值为true,则 $attrs中的值会显示在当前组件的dom节点的属性中。

将子组件中的inheritAttrs设置为true,可以看到,除被其接受到的name外,其他父组件传的参数,都显示到了其根节点的属性中。
在这里插入图片描述

二、$listeners内容

$listeners是什么?

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

上面是vue官方文档对$listeners的定义,结合上面所提到的 $attrs,是不是感觉两者特别相似。
$attrs内接受的是父组件所传递的属性,而 $listeners内接受的则是父组件中所传递的方法

$listeners能做些什么?

根据上方官方文档的说法,它可以通过 v-on=“$listeners” 传入内部组件。即把父组件中的事件监听,并传递到其所有后代。
试问一下,提到子组件向父组件传参,我们最常用方式,是不是用 $emit()方法,来调用父组件中的自定义事件。

而使用 v-on="$listeners" ,只要使用得当,即可优雅的在任何后代元素中,改变父组件的值,可谓是一个十分强大的功能。

$listeners使用方式

父组件

<template>
  <div>
    <div class="father">
      <span>父组件</span>
      <span>name:{{ name }}</span>
    </div>
    <son name="name" @changeName="changeName"/>
  </div>
</template>

<script>
import Son from "./Son";
export default {
  name: "Father",
  components: {Son},
  data() {
    return {
      name: 'Rise'
    }
  },
  methods: {
    changeName(name) {
      this.name = name
    }
  }
}
</script>

子组件

<template>
  <div>
    <div class="son">
      <span>子组件</span>>
    </div>
    <grandson v-on="$listeners"/>
  </div>
</template>

<script>
import Grandson from "./Grandson";
export default {
  name: "Son",
  components: {Grandson}
}
</script>

孙组件

<template>
  <div class="grandson">
    <div>孙组件</div>
    <div>
      <button @click="listeners()">$listeners</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "Grandson",
  methods:{
    listeners(){
      this.$emit('changeName','tim')
    }
  }
}
</script>

结果
孙组件触发changeName前:
在这里插入图片描述
孙组件触发changeName后:
在这里插入图片描述

$listeners注意事项

1. 与$attrs值被接收后,只能一个后代使用不同。$listeners支持所有后代一起使用,即子组件内使用过后,孙组件及其后代依然能够传递与调用。

结语

$attrs 与 $listeners诞生于vue2.4版本,其出现使得父孙乃至父组件与任意后代间的通信,变得更加的简单与优雅。
作为一个vue领域的学徒,以上为我的一些个人理解,一家之言。如有错误欢迎指正!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值