记录下vue的$attrs和$listeners

$attrs

官网上的类型是{ [key: string]: string },但是我试了下,如果传递是的是个对象也是可以接受到的。所以我认为这个value应该为 any 类型

  • 类型:{ [key: string]: any } //{ [key: string]: string }
  • 只读
  • 详细
    • 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
    • 简单来说就是 $attrs 可以获取其父组件接收到的所有除了当前组件 props 里面接受了的props字段 和 class/style 之外的字段

例子:

  • 目录结构
    在这里插入图片描述

这个时候如果 grandson 组件需要获取到 从 app.vue 传递过来的参数,可以使用 $attrs

  1. 首先在需要向需要接受 $attrs 的组件传递 $attrs 参数(因为是在 children 中引入的 grandson组件,所以在 children组件中给grandson传递参数即可)
<template>
    <div class="children">
        <div>这是子组件</div>
        <grandson v-bind="$attrs"></grandson>
    </div>
</template>

<script>
import grandson from './grandson.vue'
export default {
    name: 'children',
    components: { grandson }
}
</script>
  1. 在 grandson 中直接使用即可,不需要接受,如果在引入 grandson 组件的时候未绑定,则 $attrs 的值默认为 {}
<template>
    <div class="grandson">
        <pre>{{ $attrs }}</pre>
    </div>
</template>

<script>
export default {
    name: 'grandson',
    // 这里接受传递过来的参数 prop
    props: ['prop']
}
</script>
  1. 在祖先组件(app.vue)中传递参数
<template>
  <div id="app">
    <children :text="{a: 1}" :params="2" :prop="3"></children>
  </div>
</template>

<script>
import children from './components/children'
export default {
  name: 'App',
  components: {children}
}
</script>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  .children {
    width: 200px;
    height: 250px;
    border: 1px solid #ccc;
    .grandson {
      width: 150px;
      height: 180px;
      border: 1px solid #ccc;
    }
  }
}
</style>

  1. 运行项目,结果:
    在这里插入图片描述

得出结论:可以通过 $attrs 在组件中传递参数给 子孙组件,子孙组件可以通过 $attrs 获取传递给父组件下的子组件的所有非props接受的参数
注意:如果是隔代传递,无法接受。比如:给当前组件新增一个层级,parent 组件。将 parent 组件作为 children 组件的父组件。app 作为 parent 的父组件。如果在 app 中给 parent 传递参数。这个时候 grandson 是无法接受到的

可以看到传递给 $attrs的参数是 { [key: string]: any }。。。。。

$listeners

  • 类型 { [key: string]: Function | Array< Function > }
  • 只读
  • 详细
    • 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
    • 简单来说就是这玩意可以向祖先组件 emit 没有带 .native 修饰符的 事件

同一个目录,文件不做修改
例子:

  1. 还是在 children 组件中给 grandson 组件增加 $listeners 绑定
......
<!-- 给 grandson 组件新增 v-on="$listeners" -->
<grandson v-bind="$attrs" v-on="$listeners"></grandson>
......
  1. 修改 grandson 组件
<template>
    <div class="grandson">
        <pre>{{$attrs}}</pre>
        <div @click="$emit('grandsonEvent', 'grandson组件被点击')">按钮1</div>
        <div @click="$emit('grandsonEventNative', '带有.native修饰符事件触发')">按钮2</div>
    </div>
</template>
......
  1. 在app.vue中接收
<template>
  <div id="app">
    <children :text="{a: 1}" :params="2" :prop="3" @grandsonEvent="grandsonEvent" @grandsonEventNative.native="grandsonEventNative"></children>
  </div>
</template>

<script>
import children from './components/children'
export default {
  name: 'App',
  components: {children},
  methods: {
  	// 接受来自 grandson 组件传递过来的方法。没有加 .navtive修饰符
    grandsonEvent (params) {
      alert(params)
    },
    // 接受来自 grandson 组件传递过来的方法。加了 .navtive修饰符
    grandsonEventNative (params) {
      alert(params)
    }
  }
}
</script>
......
  1. 运行结果
    • 点击 按钮1,运行结果:
      在这里插入图片描述
    • 点击 按钮2,页面无反应。增加了 .navtive 修饰符的不会接收到来自非子组件的事件

所以 $listeners 就是用来 孙组件给 组件组件 emit 事件用的?。。。

如果设置了 $attrs 父组件某个参数,祖先组件也传递一样的参数,那么孙组件接受到的是谁的参数?

  1. 照原来的例子,对 children 做修改,给 grandson 传递 text 参数
......
<grandson v-bind="$attrs" v-on="$listeners" :text="0"></grandson>
......
  1. 运行项目,看效果
    在这里插入图片描述
    _ 从app.vue组件传递过来的参数被 children 组件覆盖了_
    也就是说 $attrs 接收的时候 是先接受到祖先组件的参数,然后接收父组件的参数,这个时候父组件的参数会覆盖祖先组件的值

  2. $listeners 一样。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值