$attrs和$listeners

$attrs:从父组件中接收到的,没有注册到props中的值,传递给子组件使用。如果在props中接收了,也需要传递给子组件,可以使用属性合并v-bind="{ type,  ...$attrs }"

 

$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

 

posted @ 2021-05-23 13:43  吴小明-  阅读(409)  评论(0编辑  收藏  举报