vue $attrs 和 $listeners

vm.$attrs

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

vm.$listeners

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

代码实践:
1.父组件(FatherComponent.vue),给子组件传递数据,子组件如果不显式地用props接收,那么这些数据就作为普通的HTML特性应用在子组件的根元素上,而被$attrs所拥有

// 1.创建 FatherComponent.vue
// 2.引入子组件
// 3.并给子组件绑定属性:componyList,userInfos, 绑定事件: @sendMessage
// 4.并初始化方法 sendMessage
<template>
<div class='father-container'>
  <div style="height: 30px; color: red; font-size: 16px;">我是爷爷组件</div>
  <div>
    <child-component
    :componyList="componies"
    @sendMessage="sendMessage"
    :userInfos="personInfo"></child-component>
  </div>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
  name: 'FatherComponent',
  components: {
    ChildComponent
  },
  data() {
    return {
      personInfo: {
        name: 'zhangsan',
        age: 20,
        gender: 'male',
        houseList: ['houseA', 'houseB', 'houseC']
      },
      componies: ['componyA', 'componyB', 'componyC']
    }
  },
  methods: {
  	// msg为孙子组件传递过来的数据
    sendMessage(msg, msg1) {
      console.log(`${msg} ${msg1}`)
    }
  }
}
</script>
<style lang='scss' scoped>
</style>

2.儿子组件(ChildComponent.vue)中间层,作为父组件和孙子组件的传递中介,在儿子组件中给孙子组件添加v-bind="$attrs",这样孙子组件才能接收到数据

// 1.创建子组件 ChildComponent.vue
// 2.给子组件传值,但不使用props接收
// 3.在子组件中引入孙子组件,并给孙子组件绑定 v-bind="$attrs" v-on="$listeners"
// 4.将是否继承父组件属性置为:inheritAttrs: true
<template>
<div class='child-container'>
  <div style="height: 30px; color: green; font-size: 16px;">我是儿子组件</div>
  <div>我是父组件的数据:{{this.$attrs}}</div>
  <div>我是父组件的事件:{{this.$listeners}}</div>
  <div>
    <grand-son-component v-bind="$attrs" v-on="$listeners"></grand-son-component>
  </div>
</div>
</template>
<script>
import GrandSonComponent from './GrandSonComponent.vue'
export default {
  name: 'ChildComponent',
  inheritAttrs: true,
  components: {
    GrandSonComponent
  },
  data() {
    return {}
  },
  methods: {}
}
</script>
<style lang='scss' scoped>
</style>

3.孙子组件(GrandSonComponent.vue),在孙子组件中一定要显式地用props接收从父组件传递过来的数据,这样这些属性才可以传递给孙子组件

// 1.创建孙子组件 GrandSonComponent
// 2.通过给孙子组件绑定 $attrs 和 $listeners,这样在孙子组件直接就可以获取爷爷组件中的数据了
// 3.inheritAttrs: false
// 4.那么孙子组件如何和爷爷组件通信?
// (1) this.$listeners.sendMessage(param) 
// (2) this.$emit('sendMessage', param)
<template>
<div class='grandson-container'>
  <div style="height: 30px; font-size: 16px;">我是孙子组件</div>
  <p>父传给孙子组件的数据1 userInfos: {{userInfos.name}} {{userInfos.age}} {{userInfos.gender}}</p><br>
  <p>父传给孙子组件的数据2 componyList:{{componyList}}</p>
  <button @click="triggerFatherEvent">Click Me</button>
</div>
</template>
<script>
export default {
  name: 'GrandSonComponent',
  // 不想继承所有父组件的数据,同时也不在组件根元素dom上显示
  inheritAttrs: false,
  components: {},
  //在本组件中需要声明父组件绑定的属性,来接收数据
  props: {
    componyList: {
      type: Array,
      default: () => []
    },
    userInfos: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      msg: '我是来自 GrandChild 组件的消息',
      msg1: '我是来自 GrandChild1 组件的消息'
    }
  },
  methods: {
    triggerFatherEvent() {
      // 通过this.$listeners来触发爷爷组件中的事件,并且可以传递参数
      this.$listeners.sendMessage(this.msg, this.msg1)
      // 也可以emit直接触发,这两种方式都可以向上传递数据给父组件
      // this.$emit('sendMessage', this.msg this.msg1)
    }
  }
}
</script>
<style lang='scss' scoped>
div {
  p {
    height: 30px;
  }
}
</style>

通过在子组件中绑定$attrs $listeners点击孙子组件中的click事件,可以和爷爷组件通信
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值