当前位置: 首页 > news >正文

vue3 透传 Attributes

前言

Vue 3 现在正式支持了多根节点的组件,也就是片段!

Vue 2.x 遵循单根节点组件的规则,即一个组件的模板必须有且仅有一个根元素。

为了满足单根节点的要求,开发者会将原本多根节点的内容包裹在一个<div>元素中:

<!-- Layout.vue -->
<template><div><h1>标题</h1><p>段落</p></div>
</template>

这是因为Vue 的编译器在解析组件模板时,是基于单根节点的树形结构进行处理的。如果存在多个根节点,编译器无法明确地构建组件的虚拟 DOM 结构。

因此,在Vue 2.x中,父组件在使用子组件时,写在子组件上的 classstyleid 等属性会直接传递到子组件的根元素上。

Vue 3.x 打破了 Vue 2.x 中组件模板必须有且仅有一个根元素的限制,现在组件可以包含多个根节点。

<template><h1>标题</h1><p>段落</p>
</template>

当组件存在多个根节点时,在父组件中给该组件传递属性(attribute)就需要明确指定这些属性应该绑定到哪个根节点上。如果不进行显式指定,Vue 无法确定属性的归属。

<template><ChildComponent><template v-slot:default="{ attrs }"><div v-bind="attrs">这是一个 div 根节点</div><p>这是一个 p 根节点</p><span>这是一个 span 根节点</span></template></ChildComponent>
</template>

在示例中,通过v-slot:default="{attrs}"获取到ChildComponent.vue通过插槽传递给父组件的所有属性(存储在attrs中),然后使用v-bind="attrs"将这些属性显式地绑定到其中一个根节点<div>上。

Attributes 继承

“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 propsemits 的 attribute 或者 v-on 事件监听器。

当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。

最常见的例子就是 classstyleid

子组件ChildComponent.vue的模板内容如下:

<div>这是子组件的div</div>

在父组件使用子组件ChildComponent.vue,并且传入了 classstyleid

<template><div><h1>父组件</h1><ChildComponent class="child-div"  id="child-div"style="font-size: 20px; color: brown;" /></div>
</template>
<script setup lang="ts">
import ChildComponent from './ChildComponent.vue';
</script>

渲染出的DOM结果是:

<div class="child-div" id="child-div" style="font-size: 20px; color: brown">这是子组件的div
</div>

<ChildComponent> 并没有将 classstyleid声明为它所接受的 prop,所以 classstyleid被视作透传 attribute,自动透传到了 <ChildComponent> 的根元素上。

style 属性透传到子组件的根元素后,它的生效方式与直接在 HTML 元素上设置 style 属性是一样的:
在这里插入图片描述

自动合并 classstyle

如果一个子组件的根元素已经有了 classstyle attribute,它会和从父组件上继承的值合并。

给子组件ChildComponent.vue加上classstyleid属性:

<divclass="child-box"id="child-box"style="padding: 15px; background-color: #f8f8f8"
>这是子组件的div
</div>

渲染出的DOM结果是:

<divclass="child-box child-div"id="child-div"style="padding: 15px;background-color: rgb(248, 248, 248);font-size: 20px;color: brown;"
>这是子组件的div
</div>

子组件的classstyle 属性值 和 从父组件上继承的值合并,子组件的 id 属性值被从父组件继承的 id 属性值覆盖。

页面渲染结果如下图:
在这里插入图片描述

v-on 监听器继承

子组件ChildComponent.vue的模板内容如下:

<div @click="console.log('子组件的点击事件被触发了')"> 这是子组件的div </div>

在父组件中,给<ChildComponent>绑定一个点击事件:

<template><div class="home-wrap"><h1>父组件</h1><ChildComponent @click="console.log('在父组件中,给子组件绑定的点击事件被触发了!')"/></div>
</template>
<script setup lang="ts">
import ChildComponent from './ChildComponent.vue';
</script>

父组件中绑定的click 监听器会被添加到 <ChildComponent> 的根元素:子组件的 <div> 元素之上。
子组件的<div>元素自身也通过 v-on 绑定了一个事件监听器。

当点击子组件的<div>元素,子组件的click监听器和从父组件继承的监听器都会被触发:
在这里插入图片描述

深层组件继承

有些情况下一个组件会在根节点上渲染另一个组件。

ChildComponent.vue的根节点渲染的是另一个组件GrandChild.vue时:

<!-- ChildComponent.vue 的模板,只是渲染另一个组件:<GrandChild /> -->
<template><GrandChild />
</template>

此时 <ChildComponent> 接收的透传 attribute 会直接继续传给 <GrandChild>

注意:

  1. 透传的 attribute 不会包含 <ChildComponent> 上声明过的 props 或是针对 emits 声明事件的 v-on 侦听函数,换句话说,声明过的 props 和侦听函数被 <ChildComponent> “消费”了。

  2. 透传的 attribute 若符合声明,也可以作为 props 传入 <GrandChild>

禁用 Attributes 继承

在选项式API中,在组件选项中设置 inheritAttrs: false 可以禁止 组件自动地继承 attribute。

在组合式API中,在 <script setup> 中使用 defineOptions

<script setup>
defineOptions({inheritAttrs: false
})
// ...setup 逻辑
</script>

通过设置 inheritAttrs 选项为 false,可以完全控制透传进来的 attribute 被如何使用。

注意:透传进来的 attribute 可以在模板的表达式中直接用 $attrs 访问到

ChildComponent.vue中,设置 inheritAttrs: false 并通过$attrs访问透传属性 customValue

<!-- ChildComponent.vue 的模板 -->
<template><div>在ChildComponent.vue中,读取透传 Attributes: {{ $attrs.customValue }}</div>
</template>
<script setup lang="ts">
defineOptions({inheritAttrs: false
})
</script>

在父组件中,使用子组件ChildComponent.vue,传递class属性、customValue属性:

<template><div class="home-wrap"><h1>父组件</h1><ChildComponent class="child-div" :customValue="customValue" /></div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const customValue = ref(10)
</script>

渲染出的DOM结果是:

<div>在ChildComponent.vue中,读取透传 Attributes: 10</div>

可以看到,父组件传的class属性并没有被直接透传到子组件的根元素上。

通过Vue Devtools查看$attrs$attrs 包含了 透传进来的 classcustomValue属性:
在这里插入图片描述
$attrs 对象包含了除组件所声明的 propsemits 之外的所有其他 attribute,例如 classstylev-on 监听器等等。

  • props 有所不同,透传 attributes 在 JavaScript 中保留了它们原始的大小写,所以像 foo-bar 这样的一个 attribute 需要通过 $attrs['foo-bar'] 来访问。

  • @click 这样的一个 v-on 事件监听器将在此对象下被暴露为一个函数 $attrs.onClick

通过设定 inheritAttrs: false 和使用 v-bind="$attrs" 来实现将 透传 attribute 应用在合适的元素上:

<!-- ChildComponent.vue 的模板 -->
<template><div><div v-bind:="$attrs">在ChildComponent.vue中,读取透传 Attributes: {{ $attrs.customValue }}</div></div>
</template>
<script setup lang="ts">
defineOptions({inheritAttrs: false
})
</script>

渲染出的DOM结果是:

<div><div class="child-div" customvalue="10">在ChildComponent.vue中,读取透传 Attributes: 10</div>
</div>

通过不带参数的 v-bind,将一个对象的所有属性都作为 attribute 应用到目标元素上。

多根节点的 Attributes 继承

和单根节点组件有所不同,有着多个根节点的组件没有自动 attribute 透传行为。如果 $attrs 没有被显式绑定,将会抛出一个运行时警告。

修改ChildComponent.vue

<!-- ChildComponent.vue 的模板 -->
<template><h2>ChildComponent的标题</h2><div>ChildComponent的内容</div>
</template>

此时,ChildComponent.vue是多根节点模板,由于 Vue 不知道要将 attribute 透传到哪里,所以会抛出一个警告:

Extraneous non-props attributes (class, customValue) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.

ChildComponent.vue有多个根节点时,需要显式绑定 $attrs

<!-- ChildComponent.vue 的模板 -->
<template><h2 v-bind="$attrs">ChildComponent的标题</h2><div>ChildComponent的内容</div>
</template>

在 JavaScript 中访问透传 Attributes

在选项式API中,attrs 会作为 setup() 上下文对象的一个属性暴露:

<script>
export default {setup(props, ctx) {// 透传 attribute 被暴露为 ctx.attrs,且 没有响应性console.log(ctx.attrs)}
}
</script>

在组合式API中,在 <script setup> 中使用 useAttrs() API 来访问一个组件的所有透传 attribute:

<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>

有个疑问待解决:

官网说法:attrs 对象总是反映为最新的透传 attribute,但它没有响应性,不能通过侦听器去监听它的变化。

我直接在模板中使用$attrs,以及使用上述2种方式获取attrs,修改透传 attribute 后,页面也更新了。
所以没get到,官方说的attrs对象没有响应性是指哪方面。
知道为什么的童鞋可以在评论区讲一下或者是私信给我说一下,非常感谢!

相关文章:

vue3 透传 Attributes

前言 Vue 3 现在正式支持了多根节点的组件&#xff0c;也就是片段&#xff01; Vue 2.x 遵循单根节点组件的规则&#xff0c;即一个组件的模板必须有且仅有一个根元素。 为了满足单根节点的要求&#xff0c;开发者会将原本多根节点的内容包裹在一个<div>元素中&#x…...

4.接口测试基础(Jmter工具/场景二:一个项目由多个人负责接口测试,我只负责其中三个模块,协同)

一、场景二&#xff1a;一个项目由多个人负责接口测试&#xff0c;我只负责其中三个模块&#xff0c;协同 1.什么是测试片段&#xff1f; 1&#xff09;就相当于只是项目的一部分用例&#xff0c;不能单独运行&#xff0c;必须要和控制器&#xff08;include,模块&#xff09;一…...

electron react离线使用monaco-editor

目录 1.搭建一个 electron-vite 项目 2.安装monaco-editor/react和monaco-editor 3.引入并做monaco-editor离线配置 4.react中使用 5.完整代码示例 6.monaco-editor离线配置官方说明 7.测试 1.搭建一个 electron-vite 项目 pnpm create quick-start/electron 参考链接…...

Python 的 WSGI 简单了解

从 flask 的 hello world 说起 直接讨论 WSGI&#xff0c;很多人可能没有概念&#xff0c;我们还是先从一个简单的 hello world 程序开始吧。 from flask import Flaskapp Flask(__name__)app.route("/", methods[GET]) def index():return "Hello world!&q…...

基于stm32使用ucgui+GUIBuilder开发ui实例

1 项目需求 1.1 基于Tft 触摸屏实现一个自锁按键 1.2 按键在按下后背景色需要进行变化&#xff0c;以凸显当前按键状态&#xff08;选中or 未选中&#xff09; 1.3 按键选中时对某一gpio输出低电平&#xff0c;非选中时输出高电平 2 移植 ucgui UCGUI的文件数量很大&#x…...

Spring扩展点系列-ApplicationContextAwareProcessor

文章目录 简介源码分析示例代码示例一&#xff1a;扩展点的执行顺序运行示例一 示例二&#xff1a;获取配置文件值配置文件application.properties内容定义工具类ConfigUtilcontroller测试调用运行示例二 示例三&#xff1a;实现ResourceLoaderAware读取文件ExtendResourceLoad…...

基于Keil软件实现实时时钟(江协科技HAL库)

实时时钟实验是基于江协科技STM32的HAL库工程模板创建的(可以在作品“基于江科大STM32创建的HAL库工程模板”中的结尾处获取工程模板的百度网盘链接) 复制“OLED显示”的工程文件——“4-1 OLED显示屏”,并命名为“12-2 实时时钟 ”。打开工程,把下面的程序复制到相应的文…...

dedecms靶场(四种webshell姿势)

进入靶场 姿势一&#xff1a;过文件管理器上传WebShell 步骤一&#xff1a;登录后台 /dede 步骤二&#xff1a;核心-》文件式管理-》文件上传-》上传一句话木马 点击 步骤三&#xff1a;进行蚁剑连接 姿势二&#xff1a;修改模板文件拿WebShell 步骤一&#xff1a;模板-》默认…...

PHP:强大的Web开发语言

PHP&#xff1a;强大的Web开发语言 一、PHP 简介及优势 PHP 的基本概念 PHP&#xff08;PHP: Hypertext Preprocessor&#xff09;即 “超文本预处理器”&#xff0c;是一种通用开源脚本语言&#xff0c;最初由 Rasmus Lerdorf 于 1994 年创建。它可以在服务器上执行&#xf…...

06_Python数据类型_元组

Python的基础数据类型 数值类型&#xff1a;整数、浮点数、复数、布尔字符串容器类型&#xff1a;列表、元祖、字典、集合 元组 元组&#xff08;Tuple&#xff09;是一种不可变的序列类型&#xff0c;与列表类似&#xff0c;但有一些关键的区别。本质&#xff1a;只读的列表…...

【Vue】- ref获取DOM元素和购物车案例分析

文章目录 知识回顾前言源码分析1. ref2. 购物车案例分析3. 购物车计算、全选 拓展知识数据持久化localStorage 总结 知识回顾 前言 元素上使用 ref属性关联响应式数据&#xff0c;获取DOM元素 步骤 ● 创建 ref > const hRef ref(null) ● 模板中建立关联 > <h1 re…...

【AI大模型】ChatGPT模型原理介绍(下)

目录 &#x1f354; GPT-3介绍 1.1 GPT-3模型架构 1.2 GPT-3训练核心思想 1.3 GPT-3数据集 1.4 GPT-3模型的特点 1.5 GPT-3模型总结 &#x1f354; ChatGPT介绍 2.1 ChatGPT原理 2.2 什么是强化学习 2.3 ChatGPT强化学习步骤 2.4 监督调优模型 2.5 训练奖励模型 2.…...

Python数据分析与可视化实战指南

在数据驱动的时代&#xff0c;Python因其简洁的语法、强大的库生态系统以及活跃的社区&#xff0c;成为了数据分析与可视化的首选语言。本文将通过一个详细的案例&#xff0c;带领大家学习如何使用Python进行数据分析&#xff0c;并通过可视化来直观呈现分析结果。 一、环境准…...

react18基础教程系列-- 框架基础理论知识mvc/jsx/createRoot

react的设计模式 React 是 mvc 体系&#xff0c;vue 是 mvvm 体系 mvc: model(数据)-view(视图)-controller(控制器) 我们需要按照专业的语法去构建 app 页面&#xff0c;react 使用的是 jsx 语法构建数据层&#xff0c;需要动态处理的的数据都要数据层支持控制层: 当我们需要…...

牛客周赛 Round 60 折返跑(组合数学)

题目链接&#xff1a;题目 大意&#xff1a; 在 1 1 1到 n n n之间往返跑m趟&#xff0c;推 m − 1 m-1 m−1次杆子&#xff0c;每次都向中间推&#xff0c;不能推零次&#xff0c;问有多少种推法&#xff08;mod 1e97&#xff09;。 思路&#xff1a; 一个高中学过的组合数…...

深入浅出Java匿名内部类:用法详解与实例演示

匿名内部类&#xff08;Anonymous Inner Class&#xff09;在Java中是一种非常有用的特性&#xff0c;它允许你在一个类的定义中直接创建并实例化一个内部类&#xff0c;而不需要为这个内部类指定一个名字。匿名内部类通常用于以下几种情况&#xff1a; 实现接口&#xff1a;当…...

数据库MySQL、Mariadb、PostgreSQL、MangoDB、Memcached和Redis详细介绍

以下是一些常见的后端开发数据库选型&#xff1a; 关系型数据库&#xff08;RDBMS&#xff09;&#xff1a;关系型数据库是最常见的数据库类型&#xff0c;使用表格和关系模型来存储和管理数据。常见的关系型数据库包括MySQL、PostgreSQL和Oracle等。这些数据库适合处理结构化数…...

【ArcGIS Pro实操第七期】栅格数据合并、裁剪及统计:以全球不透水面积为例

【ArcGIS Pro实操第七期】批量裁剪&#xff1a;以全球不透水面积为例 准备&#xff1a;数据下载ArcGIS Pro批量裁剪数据集1 数据拼接2 数据裁剪3 数据统计&#xff1a;各栅格取值3.1 栅格计算器-精确提取-栅格数据特定值3.2 数据统计 4 不透水面积变化分析 参考 准备&#xff1…...

【Linux】Image、zImage与uImage的区别

1、Image 1.1 什么是 Image Image 是一种未压缩的 Linux 内核镜像文件&#xff0c;包含了内核的所有代码、数据和必要的元信息。它是 Linux 内核在编译过程中生成的一个原始的二进制文件&#xff0c;未经过任何压缩或额外的封装处理。由于未压缩&#xff0c;Image 文件相对较…...

算子加速(3):自定义cuda扩展

需要自定义某个层,或有时候用c++实现你的操作(c++扩展)可能会更好: 例如:需要实现一个新型的激活函数例如: bevfusion用cuda实现bevpool加速自定义扩展的步骤 (1) 首先用纯pytorch和python 实现我们所需的功能,看看效果再决定要不要进一步优化(2) 明确优化方向,用C++ (或CU…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...

21-Oracle 23 ai-Automatic SQL Plan Management(SPM)

小伙伴们&#xff0c;有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL&#xff0c; 性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。 于是SPM定位开始&#xff0c;OCM考试中SPM必考。 其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题…...

C++ Saucer 编写Windows桌面应用

文章目录 一、背景二、Saucer 简介核心特性典型应用场景 三、生成自己的项目四、以Win32项目方式构建Win32项目禁用最大化按钮 五、总结 一、背景 使用Saucer框架&#xff0c;开发Windows桌面应用&#xff0c;把一个html页面作为GUI设计放到Saucer里&#xff0c;隐藏掉运行时弹…...