Vue3中的常见组件通信之$attrs

Vue3中的常见组件通信之$attrs

概述

​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refsparent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。

组件关系 传递方式
父传子 1. props
2. v-model
3. $refs
4. 默认插槽、具名插槽
子传父 1. props
2. 自定义事件
3. v-model
4. $parent
5. 作用域插槽
祖传孙、孙传祖 1. $attrs
2. provide、inject
兄弟间、任意组件间 1. mitt
2. pinia

props和自定义事件详见:
Vue3中的常见组件通信之props和自定义事件
mitt用法详见:
Vue3中的常见组件通信之mitt
v-model用法详见:
Vue3中的常见组件通信之v-model
接下是$attrs的用法。

5.$attrs

$attrs用于当前组件的父组件与当前组件的子组件相互通信,也就是祖孙间通信。

5.1准备三个组件

首先准备三个组件,Father组件代码如下:

<template>
  <div class="father">
    <h3>父组件</h3>
		<Child/>
  </div>
</template>

<script setup lang="ts" name="Father">
	import Child from './Child.vue'	
	
</script>

<style scoped>
	.father{
		background-color: rgb(74, 108, 110);
		padding: 20px;
		color: #fff;
	}
</style>

Child组件代码如下:

<template>
	<div class="child">
		<h3>子组件</h3>
		<GrandChild/>
	</div>
</template>

<script setup lang="ts" name="Child">
	import GrandChild from './GrandChild.vue'
</script>

<style scoped>
	.child{
		margin-top: 20px;
		background-color: rgb(213, 217, 219);
		padding: 20px;
		color: #000;
	}
</style>

GrandChild组件代码如下:

<template>
	<div class="grand-child">
		<h3>孙组件</h3>		
	</div>
</template>

<script setup lang="ts" name="GrandChild">
	
</script>

<style scoped>
	.grand-child{
		margin-top: 20px;
		background-color: rgb(164, 85, 31);
		padding: 20px;
		color: #fff;		
	}
</style>

运行后效果如下:

image-20240606210643288

5.2祖传孙的实现

首先给父组件添加一些数据:

	import {ref} from 'vue'
	//数据
	let a = ref(100)
	let b = ref(200)
	let c = ref(300)

然后在父组件页面上呈现出来:

<ul>
    <li>a: {{ a }}</li>
    <li>b: {{ b }}</li>
    <li>c: {{ c }}</li>
</ul>

同时将数据传给Child组件:

<Child :a="a" :b="b" :c="c"/>

接下来再写Child组件的代码,首先要接收数据:

//接收props
defineProps(['a'])

页面呈现出来如下:

<ul>
    <li>a: {{ a }}</li>
</ul>

呈现效果如下:

image-20240606212625201

注意父组件给子组件传递了abc三个数据,但是子组件只接收了一个数据a,那么剩下的两个bc数据去哪里了呢?此时需要借助浏览器的vue开发者工具,打开后可以看到b和c的数据在attrs里。

image-20240606220635359

在页面呈现一下attrs:

<ul>
    <li>a: {{ a }}</li>
    <li>其他: {{ $attrs }}</li>
</ul>

页面效果如下:

image-20240606221703370

可以看出来$attrs是个对象格式的数据,这样Child组件就可以把attrs的数据传递给GrandChild组件:

<!-- 将attrs传给GrandChild -->
<GrandChild :="$attrs"/>

**注意:**上面的代码等价于下面的代码:

<GrandChild v-bind="$attrs"/>

由于$attrs的值是对象{‘‘b’’:200,“c”:300},所以上的代码又等价于:

<GrandChild :b="b" :c="c"/>

然后在GrandChild组件中接收b和c:

defineProps(['b','c'])

并在页面呈现:

<ul>    
    <li>b: {{ b }}</li>
    <li>c: {{ c }}</li>
</ul>

运行结果如下:

image-20240606223253971

这样就实现了祖传孙的过程,在上面的代码中,Child组件也可以不接收任何props,Father组件传的所有的数据都通过$attrs传给GrandChild组件,运行效果如下:

image-20240606223648082

5.3孙传祖的实现

如果实现孙传祖的效果,需要在Father组件中给Child传递一个函数,GrandChild组件接收后触发这个函数,与props实现子传父的做法一致,如下是在Father组件中定义函数如下:

function changeA(value:number){
    a.value += value
}

传给Child组件:

<Child :a="a" :b="b" :c="c" :changeA="changeA"/>

在GrandChild组件中接收:

defineProps(['a','b','c','changeA'])

再添加一个按钮,绑定定click事件,触发函数,并传递参数:

<button @click="changeA(100)">点我更改父组件中a的值增加100</button>

这样就实现了孙传祖的过程,当点击按钮时,Father组件中的a值会增加100,每点击一次增加100,这个新的值也会再传给GrandChild,实现的效果就是点击按钮后Father组件和GrandChild组件中的a值会同时变化,如下图所示:

以下是各个组件的完整代码:

Father组件:

<template>
  <div class="father">
    <h3>父组件</h3>
	<ul>
		<li>a: {{ a }}</li>
		<li>b: {{ b }}</li>
		<li>c: {{ c }}</li>
	</ul>
	<Child :a="a" :b="b" :c="c" :changeA="changeA"/>
  </div>
</template>

<script setup lang="ts" name="Father">
	import Child from './Child.vue'	
	import {ref} from 'vue'

	//数据
	let a = ref(100)
	let b = ref(200)
	let c = ref(300)

	function changeA(value:number){
		a.value += value
	}

</script>

<style scoped>
	.father{
		background-color: rgb(74, 108, 110);
		padding: 20px;
		color: #fff;
	}
</style>

Child组件:

<template>
	<div class="child">
		<h3>子组件</h3>
		<!-- <ul>
			<li>a: {{ a }}</li>
			<li>其他: {{ $attrs }}</li>
		</ul> -->
		<!-- 将attrs传给GrandChild -->
		<GrandChild :="$attrs"/>
	</div>
</template>

<script setup lang="ts" name="Child">
	import GrandChild from './GrandChild.vue'
	//接收props
	// defineProps(['a'])
</script>

<style scoped>
	.child{
		margin-top: 20px;
		background-color: rgb(213, 217, 219);
		padding: 20px;
		color: #000;
	}
</style>

GrandChild组件

<template>
	<div class="grand-child">
		<h3>孙组件</h3>		
		<ul>
			<li>a: {{ a }}</li>
			<li>b: {{ b }}</li>
			<li>c: {{ c }}</li>
		</ul>
		<button @click="changeA(100)">点我更改父组件中a的值增加100</button>
	</div>
</template>

<script setup lang="ts" name="GrandChild">

//接收props
defineProps(['a','b','c','changeA'])
	
</script>

<style scoped>
	.grand-child{
		margin-top: 20px;
		background-color: rgb(164, 85, 31);
		padding: 20px;
		color: #fff;		
	}
	button{
		color: #000;
	}
</style>

5.4小结

$attrs用于祖孙间的通信,$attrs是一个对象,包含所有父组件传入的标签属性。

相关推荐

  1. Vue组件通信

    2024-06-10 20:20:02       7 阅读
  2. vue组件通信

    2024-06-10 20:20:02       9 阅读
  3. VUE组件常用通信方式有哪些?

    2024-06-10 20:20:02       18 阅读
  4. vue笔记$attr

    2024-06-10 20:20:02       40 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 20:20:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-10 20:20:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-10 20:20:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-10 20:20:02       18 阅读

热门阅读

  1. 深入解析分布式链路追踪:原理、技术及应用

    2024-06-10 20:20:02       11 阅读
  2. electron录制工具-desktopCapturer录屏

    2024-06-10 20:20:02       10 阅读
  3. multisim仿真电路图

    2024-06-10 20:20:02       11 阅读
  4. 公式面试题总结(三)

    2024-06-10 20:20:02       8 阅读
  5. 【设计模式】基本名词

    2024-06-10 20:20:02       11 阅读
  6. leetcode290:单词规律

    2024-06-10 20:20:02       13 阅读
  7. 回溯算法复原ip,子集1和子集2

    2024-06-10 20:20:02       9 阅读
  8. 43.django里写自定义的sql进行查询

    2024-06-10 20:20:02       7 阅读