前言:爷孙组件使用prop一层一层传值和方法由于比较简单这里就不讲了,主要讲解使用$attrs是如何解决爷孙组件传值的

1:setup函数传递属性和方法($attrs)

1:代码
// 爷组件  grandFather.vue
<template>
  <div class="father">
    <h1>爷组件:{{ grandFatherMsg }}</h1>
    <Father
      :grandFatherMsg="grandFatherMsg"
      :str="'张三'"
      :num="111"
      :bol="true"
      @clickGrandFather="clickGrandFather"
      :sdfsdf="sdfsdf"
    />
  </div>
</template>
<script>
import { defineComponent, ref } from "vue";
import Father from "./father.vue";
export default defineComponent({
  components: {
    Father,
  },
  setup(prop, ctx) {
    const grandFatherMsg = ref("爷组件的值——张三");
    function clickGrandFather() {
      console.log("爷组件的log");
    }
    function sdfsdf() {
      console.log("爷组件的log222");
    }
    return {
      grandFatherMsg,
      clickGrandFather,
      sdfsdf,
    };
  },
});
</script>
// 父组件   father.vue
<template>
  <div class="father">
    <h1>父组件</h1>
    <grandSon v-bind="$attrs" />
  </div>
</template>
<script>
import { defineComponent } from "vue";
import grandSon from "./grandSon.vue";
export default defineComponent({
  components: {
    grandSon,
  },
  setup(prop, ctx) {
    console.log("父组件", prop, ctx);
    return {};
  },
});
</script>
// 孙组件   grandSon.vue
<template>
  <div class="grandSon">
    <h2>孙组件</h2>
    <button @click="clickgrandSon">点我触发爷组件</button>
  </div>
</template>
<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
  setup(prop, ctx) {
    console.log("孙组件", prop, ctx.attrs);
    // 孙组件的方法
    function clickgrandSon() {
      ctx.attrs.onClickGrandFather();
      ctx.attrs.sdfsdf();
      console.log("grandSon的log");
    }
    return {
      clickgrandSon,
    };
  },
});
</script>
<style scoped>
.grandSon {
  width: 200px;
  height: 100px;
  border: 1px solid green;
}
</style>


2:主要代码和详细讲解

在这里插入图片描述

3:注意点

(1)与父子组件不同,爷孙组件传递的方法使用@和:都是可以的如下图,但是为了更好的区分属性和方法,并不推荐使用:的形式来传递方法
在这里插入图片描述

注意点:(2):如下面代码所示,‘@’传递的方法在孙组件使用的时候,需要将方法名首字母大写,并且前面加上on关键字,而‘’传递的方法则不需要

// 孙组件的点击方法
function clickgrandSon() {
  ctx.attrs.onClickGrandFather(); // @传递的方法首字母大写,前面加上关键字on
  ctx.attrs.sdfsdf();  // : 传递的方法可以直接使用
  console.log("grandSon的log");
 }

2:script setup 语法糖传递属性和方法

1:代码
// 爷组件  grandFather.vue
<template>
  <div class="father">
    <h1>爷组件:{{ grandFatherMsg }}</h1>
    <Father
      :grandFatherMsg="grandFatherMsg"
      :str="'李四'"
      :num="111"
      :bol="true"
      @clickGrandFather="clickGrandFather"
      :sdfsdf="sdfsdf"
    />
  </div>
</template>
<script setup>
import { ref } from "vue";
import Father from "./father.vue";

const grandFatherMsg = ref("爷组件的值——李四");
function clickGrandFather() {
  console.log("爷组件的log");
}
function sdfsdf() {
  console.log("爷组件的log222");
}
</script>
<style scoped>
.father {
  width: 200px;
  height: 200px;
  border: 1px solid red;
}
</style>
// 父组件  father.vue
<template>
  <div class="father">
    <h1>父组件</h1>
    <grandSon v-bind="$attrs" />
  </div>
</template>
<script setup>
import grandSon from "./grandSon.vue";
</script>
<style scoped>
.father {
  width: 200px;
  height: 200px;
  border: 1px solid yellow;
}
</style>

// 孙组件  grandSon.vue
<template>
  <div class="grandSon">
    <h2>孙组件:{{ $attrs.grandFatherMsg }}</h2>
    <button @click="$attrs.onClickGrandFather()">点我触发爷组件方法1</button>
    <button @click="$attrs.sdfsdf()">点我触发爷组件方法2</button>
    <button @click="clickgrandSon">点我触发爷组件方法333</button>
  </div>
</template>
<script setup>
import { ref, useAttrs } from "vue";
const attrs = useAttrs();
// 孙组件的方法
function clickgrandSon() {
  console.log("孙组件的方法", attrs);
}
</script>
<style scoped>
.grandSon {
  width: 200px;
  height: 100px;
  border: 1px solid green;
}
</style>
2:主要代码和详细讲解

在这里插入图片描述

3:注意点

(1):在html内容中setup函数的页面可以直接使用 $attrs.xxx 来获取方法和属性,但这样你会发现不能使用属性进行操作,所以我依旧推荐第二种方法,但这种方法可以使得你直接调用爷组件的方法
(2):在script setup 中请你记住下面两行代码,它可以使你获取到爷组件传递过来的所有属性和方法

import { useAttrs } from "vue";
const attrs = useAttrs();

参考文章:详细了解Vue3 - $attrs 的几种用法

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐