$attrs和$listeners

Posted 吴小明

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了$attrs和$listeners相关的知识,希望对你有一定的参考价值。

$attrs:从父组件中接收到的,没有注册到props中的值,传递给子组件使用

$listeners:将子组件的自定义事件传递给父组件

 

 

如图所示,A、B、C、D四个组件的关系就是一级一级的父子关系

A组件将x传递给B使用,将y传递给C使用,将z传递给D使用并且B不需要使用y和z,C也不需要使用z,如何实现?

 

B组件中用props接收x,通过 v-bind="$attrs" 将剩下的y和z传递到C中

C组件中用props接收y,就可以使用y了,同时也可以通过 v-bind="$attrs" 将剩下的z传递到D中

D组件中用props接收z,就可以使用z了

 

在上面的过程中,如果B中通过 :x=\'x\' 将x传给了C,那么C中也可以通过props接收到x值进行使用,同理,C可以将x传递给D。这就是通过props一层一层往下传就行了,但是如果说A中的数据(z)B、C都不需要使用,只有D需要使用,那么在B、C中不要在props中接收,分别加上 v-bind="$attrs",D中通过props就可以拿到A中的z

 

那如果要从C传递一个值到A中,怎么操作呢?

 

在A中定义一个自定义事件用于接收子孙组件传来的值 @refresh="handleRefresh",在C中通过 $emit 去触发 refresh 事件,这显然是不行的

但是在B中加上 v-on="$listeners",那么C就可以触发A中的 refresh 事件了

同理,在C中加上 v-on="$listeners",那么D也可以通过 $emit 触发 refresh 事件

 

A:

<template>
  <div class="a">
    A组件
    <p>x:{{ x }}</p>
    <p>y:{{ y }}</p>
    <p>z:{{ z }}</p>
    <B :x="x" :y="y" :z="z" @refresh="handleRefresh"></B>
  </div>
</template>
<script>
import B from \'./B\'
export default {
  data() {
    return {
      x: \'xxx\',
      y: \'yyy\',
      z: \'zzz\'
    }
  },
  methods: {
    handleRefresh(data) {
      console.log(\'刷新\', data)
    }
  },
  components: { B }
}
</script>
<style lang="less" scoped>
.a {
  width: 700px;
  height: 700px;
  background-color: red;
}
</style>
View Code

B:

<template>
  <div class="b">
    B组件
    <p>A组件x:{{ x }}</p>
    <C :x="x" v-bind="$attrs" v-on="$listeners"></C>
  </div>
</template>
<script>
import C from \'./C\'
export default {
  props: [\'x\'],
  components: { C }
}
</script>
<style lang="less" scoped>
.b {
  width: 400px;
  height: 400px;
  background-color: gold;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>
View Code

C:

<template>
  <div class="c">
    C组件
    <p>A组件x:{{ x }}</p>
    <p>A组件y:{{ y }}</p>
    <button @click="handleBtn">按钮</button>
    <D v-bind="$attrs" v-on="$listeners"></D>
  </div>
</template>
<script>
import D from \'./D\'
export default {
  methods: {
    handleBtn() {
      this.$emit(\'refresh\', \'CCC\')
    }
  },
  props: [\'x\', \'y\'],
  components: { D }
}
</script>
<style lang="less" scoped>
.c {
  width: 250px;
  height: 250px;
  background-color: greenyellow;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>
View Code

D:

<template>
  <div class="d">
    D组件
    <p>A组件z:{{ z }}</p>
    <button @click="handleBtn">按钮</button>
  </div>
</template>
<script>
export default {
  methods: {
    handleBtn() {
      this.$emit(\'refresh\', \'DDD\')
    }
  },
  props: [\'z\']
}
</script>
<style lang="less" scoped>
.d {
  width: 100px;
  height: 100px;
  background-color: deeppink;
}
</style>
View Code

 

以上是关于$attrs和$listeners的主要内容,如果未能解决你的问题,请参考以下文章

vue-$attrs和$listeners

vue $attrs、$listeners使用

Vue2.x $attrs和$listeners

Vue2.x $attrs和$listeners

Vue 警告 $listeners 和 $attrs 是只读的

Vue 学习笔记:$attrs 和 $listeners 的用法