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手动绑定未声明的属性至所需位置,确保了属性传递的灵活性与可控性。

相关推荐
剪刀石头布啊5 分钟前
泛洪DFS、BFS
前端
qetfw5 分钟前
Windows Server AD CS:根 CA、Web 证书模板与域内自动注册
前端·windows·windows-server
剪刀石头布啊6 分钟前
为什么React组件很少前缀,而vue的不少组件都有前缀
前端
剪刀石头布啊11 分钟前
gird网格布局
前端
瞬时出道12 分钟前
AI 回答为什么能一个字一个字蹦出来?前端搞懂 SSE 这一篇就够了
vue.js
啃火龙果的兔子13 分钟前
Google Chrome(谷歌浏览器)常用快捷键
前端·chrome
剪刀石头布啊15 分钟前
js真的是单线程实现异步并发么?
前端
剪刀石头布啊20 分钟前
js中改变this指向的操作有哪些
前端
剪刀石头布啊20 分钟前
vue、react 列表中使用 index 作为 key 的话,修改某一个元素后会发生什么
前端
方方洛22 分钟前
glowglow:语言无关的语法高亮器是怎么实现的
前端·前端框架