使用$attrs,$listeners进行爷孙组件通信

转载:详细讲解vue中祖孙组件间的通信之使用$attrs和$listeners的方式 - 知乎

项目结构图

$attrs

$attrs是一个容器对象,用来存放该组件的父组件传来的,且未使用props进行声明获取的数据

爷组件:

<template>
  <div id="app">
    我是爷组件
    <fu
      :msg1="msg1"
      :msg2="msg2"
      :msg3="msg3"
      :msg4="msg4"
    ></fu>
  </div>
</template>

<script>
import fu from "./views/fu.vue";
export default {
  components: {
    fu,
  },
  data() {
    return {
      msg1: "孙悟空",
      msg2: "猪八戒",
      msg3: ["白骨精", "玉兔精", "狐狸精"],
      msg4: {
        name: "炎帝萧炎",
        book: "斗破苍穹",
      },
    };
  },
};
</script>
<style lang="less" scoped>
#app {
  width: 950px;
  height: 600px;
  box-sizing: border-box;
  border: 3px dashed #e9e9e9;
  background-color: #cde;
  margin: 50px;
}
</style>

此时爷组件通过:(v-bind)向父组件中传递了四个数据,此时在父组件中的$attrs会存放爷组件传递过去的,且未进行props声明的数据

<template>
  <div class="fatherClass">
    我是父组件
    <h2>{{ msg1 }}</h2>
    <h2>{{ $attrs.msg2}}</h2>
    <h2>{{ $attrs.msg3}}</h2>
    <h2>{{ $attrs.msg4}}</h2>
  </div>
</template>

<script>
export default {
  name: "DemoFather",
  props: {
    msg1: {
      type: String,
      default: "",
    },
  },
  mounted() {
    console.log('fu组件实例',this);
  },
};
</script>
<style lang="less" scoped>
.fatherClass {
  width: 850px;
  height: 400px;
  background-color: #baf;
  margin-left: 50px;
  margin-top: 50px;
}
</style>

此时在父组件中再通过v-bind="$attrs",将爷组件传来的数据再传送给孙组件,即可实现爷孙组件的通信,在孙组件中正常接收。

<template>
  <div class="sunClass">
    我是孙子组件
    <h2>接收爷组件数据:-->{{ msg2 }}</h2>
    <h2>接收爷组件数据:-->{{ msg3 }}</h2>
    <h2>接收爷组件数据:-->{{ msg4 }}</h2>
  </div>
</template>

<script>
export default {
  // $attrs一般搭配interitAttrs 一块使用
  inheritAttrs: false, // 默认会继承在html标签上传递过来的数据,类似href属性的继承
  /*
    孙子组件通过props,就能接收到父组件传递过来的$attrs了,就能拿到里面的数据了,也就是:
    爷传父、父传子。即:祖孙之间的数据传递。
  */ 
  props: {
    msg2: {
      type: String,
      default: "",
    },
    msg3: {
      type: Array,
      default: () => {
        return [];
      },
    },
    msg4: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  name: "DemoSun",
};
</script>

<style lang="less" scoped>
.sunClass {
  width: 750px;
  height: 180px;
  background-color: #bfa;
  margin-top: 80px;
  margin-left: 50px;
}
</style>

$listeners

inheritAttrs默认值true,继承父组件除props之外的所有属性;为false只继承class属性。

通过父组件也可将孙组件的数据传递到爷组件中。$listeners将孙组件的emit方法通知到爷组件中。

1.在父组件中给孙组件的调用加上

<sun v-bind="$attrs" v-on="$listeners"></sun>

2.在爷组件中定义事件,并将事件传给父组件

<template>
  <div id="app">
    我是爷组件
    <h3>{{ fromSunData }}</h3>
    <fu :msg1="msg1" :msg2="msg2" :msg3="msg3" :msg4="msg4" 
        @fromSun="fromSun">
    </fu>
  </div>
</template>

<script>
import fu from "./views/fu.vue";
export default {
  components: {
    fu,
  },
  data() {
    return {
      msg1: "孙悟空",
      msg2: "猪八戒",
      msg3: ["白骨精", "玉兔精", "狐狸精"],
      msg4: {
        name: "炎帝萧炎",
        book: "斗破苍穹",
      },
      fromSunData: "",
    };
  },
  methods: {
    fromSun(payload) {
      console.log("孙传祖", payload);
      this.fromSunData = payload;
    },
  },
};
</script>

3.孙组件触发爷组件的事件

<template>
  <div class="sunClass">
    我是孙子组件
    <h2>接收爷组件:-->{{ msg2 }}</h2>
    <h2>接收爷组件:-->{{ msg3 }}</h2>
    <h2>接收爷组件:-->{{ msg4 }}</h2>
    <el-button size="small" type="primary" plain @click="sendToZu">孙传祖</el-button>
  </div>
</template>

<script>
export default {
  // $attrs一般搭配interitAttrs 一块使用
  inheritAttrs: false, // 默认会继承在html标签上传递过来的数据,类似href属性的继承
  props: {
    msg2: {
      type: String,
      default: "",
    },
    msg3: {
      type: Array,
      default: () => {
        return [];
      },
    },
    msg4: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  name: "DemoSun",
  data() {
    return {
      data: "来自孙组件的数据",
    };
  },
  methods: {
    sendToZu() {
      // 孙组件能够触发爷组件的fromSun方法的原因还是因为父组件中有一个$listeners作为中间人,去转发这个事件的触发
      this.$emit("fromSun", this.data);
    },
  },
};
</script>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值