学会使用$attrs跟$listeners

在父子组件通讯,或者父孙通讯

$ attrs与$ listeners的主要应用是实现多层嵌套传递。
组件A与组件B通信一般都会使用组件B中转,即A传递给B,B再给C,但是如果A到C组件之间嵌套的组件过多,需要传递的事件和属性较多,会导致代码繁琐,代码维护困难。在vue2.4中,为了解决该需求,引入了 a t t r s 和 attrs和 attrslisteners,新增了inheritAttrs选项。
在这里插入图片描述

组件数据通讯利用$attrs

官方定义:
包含了父作用域中不作为prop 被识别 (且获取) 的特性绑定 (class和 style除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class和 style除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
(好抽象一脸懵逼。。。)
a t t r s 只 代 表 的 是 那 些 没 有 被 声 明 为 p r o p s 的 属 性 , 如 果 某 个 p r o p 被 子 组 件 中 声 明 了 ( 就 是 这 个 属 性 已 经 在 子 组 件 的 p r o p s 中 了 ) , 在 子 组 件 中 的 attrs只代表的是那些没有被声明为props的属性,如果某个prop被子组件中声明了(就是这个属性已经在子组件的props中了),在子组件中的 attrspropsproppropsattr会把声明的prop剔除。
个人理解: 一个组件在父组件中被引用,$attrs就是组件标签上的静态属性值(attr)和动态属性值(:attr)的对象集合,这个集合不包含class, style和事件属性

// 父组件
<child-com class="com" name="attr" :foo="foo" :boo="boo" :coo="coo" :doo="doo" @click="test"></child-com>
...
data() {
  return {
    foo: 'Hello World!',
    boo: 'Hello Javascript!',
    coo: 'Hello Vue',
    doo: 'Last'
  }
},
...

// child-com.vue
 export default {
  name: 'childCom',
  components: {
    childCom2
  },
  created() {
    console.log(this.$attrs) // {name: "attr", foo: "Hello World!", boo: "Hello Javascript!", coo: "Hello Vue", doo: "Last"}
  }
}

如果子组件声明了 p r o p , prop, propattrs中与$props相同的属性会被移除

// child-com.vue
 export default {
  name: 'childCom',
  props: ['foo'], // foo被声明
  components: {
    childCom2
  },
  created() {
    console.log(this.$attrs) // {name: "attr", boo: "Hello Javascript!", coo: "Hello Vue", doo: "Last"}
  }
}

如果childCom里的子组件还用到foo,可以继续将foo传给子组件

//如果child的子组件c还有一个是其父组件(child组件)的prop属性,
//不是在c组件绑定的,那么c组件的$attrs组件就有这个组件,即
<template>
  <div>
    <p>foo: {{foo}} </p>
    <child-com2 :foo="foo" v-bind="$attrs"></child-com2>
  </div>
</template>

<script>
const childCom2 = () => import('./childCom2.vue')
export default {
  name: 'childCom1',
  props: ['foo'], // foo作为props属性绑定
  inheritAttrs: false,
  components: {
    childCom2
  },
  created() {
    console.log(this.$attrs) // {name: "attr", boo: "Hello Javascript!", coo: "Hello Vue", doo: "Last"}
  }
}
</script>

//childCom2.vue
created() {
    console.log(this.$attrs) // {foo: "Hello World!", name: "attr", boo: "Hello Javascript!", coo: "Hello Vue", doo: "Last"}
  }

inheritAttrs要设置成false还是true(默认)
如果inheritAttrs设置成false那么在html里的标签那些属性就不会显示
如果inheritAttrs设置成true那么在html里的标签那些属性就会显示(每一层都有)

在这里插入图片描述
在这里插入图片描述

props必须在组件中注册了props才能用拿到值,所以在嵌套层级比较深的组件中$attrs拿值更加便捷

$listeners的使用

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过v-on=”$listeners”传入内部组件。
归纳起来也是两点:

$ listeners是组件的内置属性,它的值是父组件(不含.native修饰器的) v-on事件监听器。
组件可以通 过在自己的子组件上使用v-on=”$ listeners”,进一步把值传给自己的子组件。如果子组件已经绑定$ listener中同名的监听器,则两个监听器函数会以冒泡的方式先后执行。
父组件:

 <template>
    <div class="test">
        <child  v-bind="{name, sex, age}" v-on="{changeName,changeAge}"></child>
    </div>
</template>

<script>
import child from './child'

export default {
    data() {
        return {
          name: '张三',
          sex: '男',
          age: 11,
        }
    },
    components: {
        child
    },
    methods: {
        changeName(name) {
            this.name = name
        },
        changeAge(age) {
            this.age = age
        }
    }
}
</script>

子组件child.vue

<template>
    <div class="child">
        child组件的$attrs {{$attrs}}
        <child-child v-bind="$attrs" v-on="$listeners" @showAttrs="showAttrs"></child-child>
    </div>
</template>

<script>
import childChild from  './child-child'
export default {
    name: "child",
    props: ['name'],
    inheritAttrs: false,
    created() {
        console.log('child', this.$listeners) 
    },
    components: {
        childChild
    },
    methods: {
        showAttrs() {
            console.log(this.$attrs)
        }
    }
}
</script>

孙子组件:child-child.vue

<template>
    <div class="child-child">
        child-child组件的$attrs {{$attrs}}
    </div>
</template>

<script>
export default {
    name: "child-child",
    inheritAttrs: false,
    created() {
      console.log('child-child',this.$listeners)  
    }
}
</script>

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值