Vue3 属性穿透

Vue3 属性穿透

Vue3 属性穿透包括自动穿透和属性绑定两种

  • 自动穿透 如果子组件只有一个根节点,父组件上的属性(class,id,style,事件,属性)就会向下流转到子组件的根节点上。
  • 属性绑定 如果子组件有多个根节点,父组件上的属性流转到子组件时,不确定绑定到哪个根节点上,这时就需要手动绑定属性到节点。

自动穿透

子组件只有一个根节点

简单样式穿透

vue 复制代码
<template>
    <button>提交</button>
</template>

父组件调用改子组件并传递 css,该样式会自动流转到子组件中。

vue 复制代码
<template>
  <div>
    <my-button class="my-button-background-color"></my-button>
  </div>
</template>
<script setup>
import MyButton from './components/my-button.vue'
</script>
<style>
.my-button-background-color{
  background-color: red;
}
</style>

如上,my-button-background-color 样式被自动添加到子组件的根节点上。

样式合并

子组件不变,父组件增加行内样式。

vue 复制代码
<template>
  <div>
    <my-button class="my-button-background-color" style="border: 2px solid green;"></my-button>
  </div>
</template>
<script setup>
import MyButton from './components/my-button.vue'
</script>
<style>
.my-button-background-color{
  background-color: red;
}
</style>

如上,行内样式也增加到了根节点。

监听事件

子组件不变,父组件增加监听事件。

vue 复制代码
<template>
  <div>
    <my-button class="my-button-background-color" style="border: 2px solid green;" @click="handleClick"></my-button>
  </div>
</template>
<script setup>
import MyButton from './components/my-button.vue'
const handleClick = () => {
  alert('监听点击事件');
}
</script>
<style>
.my-button-background-color{
  background-color: red;
}
</style>

click 监听器会被添加到子组件的根元素上。当原生的 button 被点击,会触发父组件的 onClick 方法。同样的,如果原生 button 元素自身也通过 v-on 绑定了一个事件监听器,则这个监听器和从父组件继承的监听器都会被触发。

隔代穿透

儿子根节点是另一个组件,属性会继续流转。 父组件不变

vue 复制代码
# 儿子组件
<template>
    <base-button></base-button>
</template>
<script setup>
import BaseButton from './base-button.vue'
</script>
vue 复制代码
# 孙子组件
<template>
    <button>孙子组件</button>
</template>

如上,属性通过儿子组件流转到孙子组件

注意:透传的属性不包含儿子组件上声明过的 props 或是针对 emits 声明事件的 v-on 侦听函数

禁用属性穿透

在某些情况下,你可能不希望子组件继承所有的属性,而是希望对属性的传递进行更精确的控制

js 复制代码
<script setup>
defineOptions({
  inheritAttrs: false
})
</script>

在儿子节点中增加如上代码

vue 复制代码
<template>
    <base-button></base-button>
</template>
<script setup>
import BaseButton from './base-button.vue'
import {defineOptions} from 'vue'
defineOptions({
  inheritAttrs: false
})
</script>

如上,属性没有流转到儿子节点。

注意:这些流转进来的属性可以在模板的表达式中直接用 $attrs 访问到

在儿子节点中增加模版代码

vue 复制代码
<template>
    <span>流转进来的属性: {{ $attrs }}</span>
    <base-button></base-button>
</template>
<script setup>
import BaseButton from './base-button.vue'
import {defineOptions} from 'vue'
defineOptions({
  inheritAttrs: false
})
</script>

如上,可以显示传递进来的属性。

注意:

  • 流转到儿子组件的属性在JavaScript中保留了它们原始的大小写,所以像 my-button-background-color 这样的一个属性需要通过 $attrs'my-button-background-color' 来访问
  • 事件会暴露出来一个函数 $attrs.handleClick

一般在模版中我们都会设置一个根节点

vue 复制代码
<template>
    <div>
        <base-button></base-button>
    </div>
</template>

如上 这样流转进来的属性会默认绑定到根节点(div)上,如果需要绑定到 <base-button></base-button> 组件上,需要手动绑定。

vue 复制代码
<template>
    <div>
        <base-button v-bind="$attrs"></base-button>
    </div>
</template>
<script setup>
import BaseButton from './base-button.vue'
import {defineOptions} from 'vue'
defineOptions({
  inheritAttrs: false
})
</script>

多根节点属性流转

多个根节点的组件没有自动属性流转行为,需要手动绑定到一个节点。如果没有手动绑定某个节点,会有警告。

在JS中访问流转属性

使用 useAttrs() 来访问一个组件的所有流转属性。

vue 复制代码
<template>
    <base-button></base-button>
</template>
<script setup>
import BaseButton from './base-button.vue'
import { useAttrs } from 'vue';
const attrs = useAttrs()
console.log(attrs)
</script>

结语

Vue3 中,属性穿透让父组件的非props属性自动传递给子组件根元素。通过设置inheritAttrs: false可禁用此功能以实现更精细控制。禁用后,利用$attrs手动绑定未声明的属性至所需位置,确保了属性传递的灵活性与可控性。

相关推荐
Setsuna_F_Seiei3 小时前
前端的 AI 学习之路 01 之 Agent API 调用 - 和 Agent 的基础对话
前端·人工智能·ai编程
threerocks3 小时前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
徐小夕3 小时前
3分钟从想法到Agent上线:我们开源了一款AI可视化工作流“IDE”
前端·算法·github
why技术5 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端
excel5 小时前
记录升级 nuxt3 到 nuxt4 记录
前端
剑胆琴心静水深流6 小时前
全栈之路6---web集成与呈现
前端·vue.js·spring boot·分布式·spring·前端框架·npm
前端snow6 小时前
ai agent -- Memory汇总
前端
ITresearchGuest7 小时前
AI 焦虑下,前端该何去何从
前端·人工智能
Codiggerworld7 小时前
Chrome DevTools 隐藏神技:这 5 个调试技巧你可能从来没用过
前端·chrome·chrome devtools
旋生万物7 小时前
【终极实战】用Python从零“生成“一个宇宙:螺旋干涉模型的代码实现
开发语言·前端·人工智能·react.js·php·wpf