前言
面试官:
说一下常用的组件传参吧?
我:
父子组件中 props
方式;通过实例化 $refs
方式,vuex
如果是兄弟组件,可以通过 enentBus
等方式,通过emit来进行子组件数据的回调,不过也有通过 $parent
$children
的方式进行获取值,这种的项目中用的不是很多,具体的使用要看实际的场景,哪个方便用哪个。
面试官:
那一个爷组件给孙子组件传值呢,一般用什么?
我:
可以通过爷组件传值给子组件,然后再传值给孙组件,或者通过 vuex 进行通信
面试官:
你的意思是传值两层给孙子组件吗
我:
是的
面试官:
那除了你说的,还有其他实现方案吗
我:
其他的应该有吧,可能平常不怎么用
面试官:
那你回去等通知吧
这是前不算太久得一个面试题,面试结束后想着去查查还有其他啥用法呢,然后一忙就给忘了,最近项目中针对element ui
二次封装,看到了 v-bind="$attrs"
,这个属性陌生又熟悉,但是具体的用法不太清楚,就花了时间去了解了一下。
Attributes 与 $attrs 的使用
官方的文档,感觉不是那么好理解
"透传 attribute"指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on
事件监听器。最常见的例子就是 class
、style
和 id
。
当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上
我们通过案例,来看一下
js
//爷组件
<template>
<div class='app'>
爷组件
<child :name="name" :age="age" :job="job" class="grand" :style="{'font-size':'20px'}"></child>
</div>
</template>
<script setup>
import {ref} from "vue"
import child from './components/child.vue';
const name=ref("我是爷组件,我今年都98了")
const age=ref(98)
const job=ref('IT')
</script>
<style scoped>
.app{
width: 600px;
height: 600px;
padding: 20px;
background: #f4f6f8;
color: #333;
}
</style>
//父组件
<template>
<div class='app-child'>
子组件
<span style="color:red ;">{{ name }}</span>
</div>
</template>
<script setup>
import { useAttrs } from 'vue';
defineProps({
name:{
type:String
}
})
const attrs=useAttrs()
console.log(attrs)
</script>
<style scoped>
.app-child{
width: 400px;
height: 400px;
padding: 20px;
background: #1b69b8;
color: #333;
}
</style>
我们在爷组件中定义了三个属性,绑定在子组件中,同时加了 style
和 class
属性。不同的是我们在子组件中,只有name 属性通过 props 接收,其他并没有进行定义接收,通过 useAttrs()
我们获取的值就是非 props 定义的数据。通过例子官方文档的第一句话就好理解了
我们来看第二句 当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上
此时我们的子组件的根组件是只有一个div,class style 属性是可以添加上去的,但是如果我们在子组件再加一个div 和,那么这是属性就无法传递过去了
js
<template>
<div class='app-child'>
子组件
<span style="color:red ;">{{ name }}</span>
</div>
<div class="next-class">
</div>
</template>
在子组件引入孙子组件后 ,我们在孙子组件中想要获取爷组件传过来的值,此时我们在孙子组件中像子组件中那样获取值是获取不到的,那如何拿到值呢,我们可以在孙子组件中使用 $attrs
js
//子组件
<template>
<div class='app-child'>
子组件
<span style="color:red ;">{{ name }}</span>
<grandSun></grandSun>
</div>
<!-- <div class="next-class">
</div> -->
</template>
<script setup>
import grandSun from './grandSun.vue';
import { useAttrs } from 'vue';
defineProps({
name:{
type:String
}
})
const attrs=useAttrs()
// console.log(attrs)
</script>
<style scoped>
.app-child{
width: 400px;
height: 400px;
padding: 20px;
background: #1b69b8;
color: #333;
}
</style>
//孙组件
<template>
<div class='app-grand-sun'>
孙子组件
</div>
</template>
<script setup>
import { useAttrs } from 'vue';
const attrs=useAttrs() //获取祖辈传过来的值(父组件也可能加,改值)
console.log(attrs)
</script>
<style scoped>
.app-grand-sun{
width: 200px;
height: 200px;
padding: 20px;
background: #ccc;
color: #333;
}
</style>
如果爷组件和父组件传同一个值,孙子组件会接收哪个值呢。遵循就近原则
attribute 与 $attrs 相关概念
attribute
是一个在HTML中的属性,用于给HTML元素添加额外的信息。它可以包含元素的名称、值和任何其他附加信息。attribute
可以用于控制元素的行为和样式。
$attrs
是Vue.js中的一个特殊属性,用于将父组件传递给子组件的所有属性集合传递给子组件。它是一个对象,包含了父组件传递给子组件的所有属性和值。在子组件中,可以使用 $attrs
来访问这些属性。
使用 $attrs
可以实现属性的透传,即将父组件的属性传递给子组件,并在子组件中使用这些属性。这在开发可复用的组件时非常有用,可以使得组件更加灵活和可配置。
inheritAttrs
假如说我不想要继承父辈传过来的属性,主要是html类 如 class style 等 v-on 等,可以使用inheritAttrs 属性来进行禁用。 下面是官方对于属性的解释
这个 $attrs
对象包含了除组件所声明的 props
和 emits
之外的所有其他 attribute,例如 class
,style
,v-on
监听器等等。
我们通过代码来测试一下
js
// 子组件加个 class 属性
<grandSun v-bind="$attrs" class="test-inheritAttrs"></grandSun>
此时可以看到我们添加的属性,我们修改一下孙子组件的代码
js
<template>
<div class='app-grand-sun'>
<div>
孙子组件
{{ $attrs.age }}
</div>
</div>
</template>
<script setup>
import { useAttrs } from 'vue';
defineOptions({
inheritAttrs: false
}) //添加该属性
const attrs=useAttrs()
console.log(attrs)
</script>
<style scoped>
.app-grand-sun{
width: 200px;
height: 200px;
padding: 20px;
background: #ccc;
color: #333;
}
</style>
那如果我想让这个class属性加在孙子组件里层 div 上呢,那我们在这上面加上 v-bind="$attrs"
即可。改完我们看下效果
最后
虽然上面的这些知识点不是很难,但是还需要自己动手实现一下才能够知道他的用法。今天就到这里吧!