在vue3中的$attrs的变化

$listeners已被删除合并到$attrs中。
$attrs现在包括class和style属性。 也就是说在vue3中$listeners不存在了。vue2中$listeners是单独存在的。
在vue3 $attrs包括class和style属性, vue2中 $attrs 不包含class和style属性。

在vue2中的$attrs

在Vue 2中,attrs里面包含着上层组件传递的所有数据(除style和class)
当一个组件声明了prop时候,attrs里面包含除去prop里面的数据剩下的数据。
结合inheritAttrs:false,可以将传递下来的数据应用于其他元素,而不是根元素:

父组件的属性直接渲染在根节点上

父页面.vue

<template>
<div>
<TestCom title="父组件给的标题" aa="我是aa" bb="我是bb"></TestCom>
</div>
</template>
<script setup lang="ts">
import TestCom from "../../components/TestCom.vue"
</script>

子组件.vue

<template>
<div class="root-son">
<p>我是p标签</p>
<span>我是span</span>
</div>
</template>

我们发现父组件中的属性直接是渲染在了 <div class="root-son"></div>这个节点上。
变为了 <div class="root-son" title="父组件给的标题" aa="我是aa" bb="我是bb"></div>。
因为在默认情况下,父组件的属性会直接渲染在子组件的根节点上。【重点】
然后有些情况我们希望是渲染在指定的节点上。那怎么处理这问题呢?
我们的 $attrs 和 inheritAttrs: false 这一对 ”好基友“ 闪亮登场

如何让父组件的属性渲染在指定的节点上

我们可以使用 $attrs 配合 inheritAttrs: false 可以将属性渲染在指定的节点上
子组件的代码中新增 inheritAttrs: false
//子组件
<template>
<div class="root-son">
<!--所有的属性都将被这个元素p接收 -->
<p v-bind="$attrs">我是p标签</p>
<span>我是span</span>
</div>
</template>
<script lang="ts" setup>
// 不让子组件的根节点渲染属性
inheritAttrs: false
</script>

发现问题-根节点和指定节点都别渲染了属性

好家伙,你不是说  $attrs 配合 inheritAttrs: false可以将属性渲染在指定的节点上。
现在虽然渲染在指定节点上。但是根节点也有。这样不好吧。切。走了。走了。菜鸡。
这,这,这, 你别走呀。 等一会。赶紧偷偷人偷偷去官网看一下出怎么说的。 原来是这样的:
<script setup> 可以和普通的 <script> 一起使用。
普通的 <script> 在有这些情况下或许会被使用到。
比如:无法在 <script setup> 中的声明选项中去使用 inheritAttrs 或插件的自定义选项。

我们需要将代码变为如下:

<template>
<div class="root-son">
<!--所有的属性都将被这个元素p接收 -->
<p v-bind="$attrs">我是p标签</p>
<span>我是span</span>
</div>
</template> <script>
//无法在 <script setup> 中的声明选项中去使用 inheritAttrs。
//所有只有在整一个<script>
export default {
inheritAttrs: false,
customOptions: {}
}
</script>
<script lang="ts" setup>
你的代码
</script>

TMD 又又发现问题了

在浏览器中提示:[plugin:vite:vue] [@vue/compiler-sfc] <script> and <script setup> must have the same language type.
TMD 又又发现问题了。稳住,我可以的。在心里一直告诉自己,冷静点,我可以解决这个问题的。
先看看它提示 must have the same language type. 必须具有相同的语言类型
小问题就是说必须要有一个类型。我将 script 上添加一个 lang="ts"就解决了。 我感觉自己又行了。 <template>
<div class="root-son">
<p v-bind="$attrs">我是p标签</p>
<span>我是span</span>
</div>
</template>
<script lang="ts">
export default {
inheritAttrs: false,
customOptions: {}
}
</script>
<script lang="ts" setup>
</script>

简单的介绍 $listeners

$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。
它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。 我的理解:因为$listeners 可以接收父级组件中(不含.native修饰器的) v-on 事件监听器.
所以在进行组件事件传递的时候非常有用。
很多时候我们对组件进行二次封装的时候不可能将组件中的内置事件都抛出来。
这个时候 $listeners 就派上用场了。
在vue2中有 vue2中$listeners是单独存在的。vue3 被合并到$attrs中了。

vue2中 v-bind="$attrs" 和 $listeners

//子组件.vue
<template>
<div>
<el-button type="primary" @click="dialogVisible = true">点击打开 </el-button>
<el-dialog v-bind="$attrs" v-on="$listeners" :visible.sync="dialogVisible"
width="30%" :before-close="handleClose">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template> <script>
export default {
inheritAttrs: false, //不让属性直接渲染在根节点上
data() {
return {
dialogVisible: false
};
},
methods: {
handleClose(done) {
this.$confirm('确认关闭?').then(() => {
done();
}).catch(() => { });
}
}
};
</script>

//父组件.vue
<template>
<div>
<LianCom title="父组件给的标题" @open="openHandler"></LianCom>
</div>
</template> <script>
import LianCom from "../components/LianCom.vue"
export default {
components: {
LianCom
},
methods: {
openHandler() {
console.log('可以直接注册事件,因为 v-on="$listeners"会接收除了.native的原生事件')
}
}
}
</script>

vue3 v-bind="$attrs" 会接收属性和事件

//子组件
<template>
<el-button text @click="dialogTableVisible = true"> 打开 </el-button>
<el-dialog width="600px" v-bind="$attrs" v-model="dialogTableVisible" title="我是标题">
<div>我值弹窗中的内容</div>
</el-dialog>
</template>
<script lang="ts">
export default {
inheritAttrs: false,
}
</script>
<script lang="ts" setup>
import { ref } from 'vue'
const dialogTableVisible = ref(false)
</script> ps:我们没有向上抛出任何事件。
但是父组件可以调用 Element Plus 中对话框中的内置方法。
但是父页面中可以 注册 Element Plus 中对话框中的内置方法。
// 父组件
<template>
<div class="father">
<TestCom @close="closeHandler" :before-close="beforeclose" title="父组件给的标题" aa="我是aa" bb="我是bb"></TestCom>
</div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus'
import TestCom from "../../components/TestCom.vue"
// Dialog 关闭的回调
const closeHandler = () => {
console.log('Dialog 关闭的回调')
}
/*
before - close 只会在用户点击关闭按钮或者对话框的遮罩区域时被调用。
如果你在 footer 具名插槽里添加了用于关闭 Dialog 的按钮,那么可以在按钮的点击回调函数里加入 before - close 的相关逻辑。
关闭前的回调,会暂停 Dialog 的关闭. 回调函数内执行 done 参数方法的时候才是真正关闭对话框的时候.
*/
const beforeclose = (done: () => void) => {
ElMessageBox.confirm('Are you sure to close this dialog?')
.then(() => {
console.log('用户点击了确定')
done()
})
.catch(() => {
console.log('用户点击了取消')
})
}
</script>

vue3中$attrs的变化与inheritAttrs的使用的更多相关文章

  1. vue中$attrs和$listeners以及inheritAttrs的用法

    官方文档说明: 一.解释:包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外). 意思就是父组件往子组件传没有在props里声明过的值时,子组件可以通 ...

  2. 基于 vite 创建 vue3 全家桶项目(vite + vue3 + tsx + pinia)

    vite 最近非常火,它是 vue 作者尤大神发布前端构建工具,底层基于 Rollup,无论是启动速度还是热加载速度都非常快.vite 随 vue3 正式版一起发布,刚开始的时候与 vue 绑定在一起 ...

  3. 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用

    刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局对象的注入和 ...

  4. vue系列---Vue组件化的实现原理(八)

    _ 阅读目录 一. 什么是Vue组件? 如何注册组件? 1.1 全局注册组件 1.2 局部注册组件 二:组件之间数据如何传递的呢? 1) props 2) $emit 3) 使用$ref实现通信 4) ...

  5. vue 通信:父子通信、兄弟通信、跨多层通信、vuex状态管理

    之前简单做了一次vue通信方法的培训,在此记录一下培训的内容. 关于vue通信,大家最先想到的方法应该是props.ref.$emit.$parent,还有vuex,因为这也是我在项目中最常用到的方法 ...

  6. 关于vue3的inheritAttrs属性和$attrs的部分用法

    当我们在父组件中想要为子组件的某一个标签添加一些样式(注意,这里的是指attributes,css样式只是其中一种属性而已) <show-message id="lkx" c ...

  7. Vue3.x 关于组件的那些变化(新手必看篇)

    一.组件内的 data 为什么总是函数形式? 我们试着先做一个计数器案例,把 data 的返回形式修改成一个对象.具体的代码如下: <template> <div> <b ...

  8. vue3渲染函数(h函数)的变化

    vue3 渲染函数(h函数)的更改 h函数的更改总结 1==>h 现在全局导入,而不是作为参数传递给渲染函数 2==>渲染函数参数更改为在有状态组件和函数组件之间更加一致 3==>v ...

  9. vue2 inheritAttrs、attrs和attrs和listeners使用

    inheritAttrs.attrs和attrs和listeners使用场景: 组件传值,尤其是祖孙组件有跨度的传值. (1)inheritAttrs 属性说明:https://cn.vuejs.or ...

随机推荐

  1. 我分析30w条数据后发现,西安新房公摊最低的竟是这里?

    前两天一个邻居发出了灵魂质问:"为什么我买的180平和你的169平看上去一样大?" "因为咱俩的套内面积都是138平......" 我们去看房子,比较不同楼盘的 ...

  2. 使用fontforge修改字体,只保留数字

    设计图上的数字采用了Roboto字体,原字体文件200多k,而小程序主包最大2m,承受不起这么大的字体.因为只用到了数字,所以可以使用fontforge编辑字体,删除多余的部分. 一.下载并安装fon ...

  3. postgresql用户与权限管理

    pg使用角色的概念管理数据库访问权限,角色是一系列相关权限的集合.为了管理方便,通常把一系列先关的权限赋予给一个角色,如果哪个用户需要这些权限,就把这些角色赋予给响应的用户. 由于用户也拥有一系列的相 ...

  4. 如何使用.NET 6的IHostedService和BackgroundService?

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 本章是<定制ASP NET 6.0框架系列文章>的第七篇.本文内容和定 ...

  5. 刷题记录:LC1997-访问完所有房间的第一天

    LC1997-访问完所有房间的第一天 题意 这里有 n 个房间,从 0 到 n-1 编号. 你每天访问一个房间,第 0 天访问第 0 号房间. 接下来,你访问房间的[次序]将根据下面的[规则]决定: ...

  6. [SDR] GNU Radio 系列教程(一) —— 什么是 GNU Radio

    目录 1.GNU Radio 是什么 2.我为什么要用 GNU Radio 3.数字信号处理 3.1 一点信号理论 3.2 将数字信号处理应用于无线电传输 4.基于流程图的模块化数字信号处理方法 本文 ...

  7. 用Python实现广度优先搜索

    图是一种善于处理关系型数据的数据结构,使用它可以很轻松地表示数据之间是如何关联的 图的实现形式有很多,最简单的方法之一就是用散列表 背景 图有两种经典的遍历方式:广度优先搜索和深度优先搜索.两者是相似 ...

  8. 全局索引与分区索引对于SQL性能影响的比较

    KingbaseES 提供了对于分区表 global index 的支持.global index 不仅提供了对于唯一索引功能的改进(无需包含分区键),而且在性能上相比非global index (l ...

  9. Linux_ps总结

    ps命令用于监测进程的工作情况.进程是一直处于动态变化中,而ps命令所显示的进程工作状态时瞬间的 使用方式: ps [options] 常用参数 -A 显示所有进程 -a 显示现行终端机下的所有进程, ...

  10. 如何结合整洁架构和MVP模式提升前端开发体验(二) - 代码实现篇

    上一篇文章介绍了整体架构,接下来说说怎么按照上图的分层结构实现下面的增删改查的功能. 代码结构 vue userManage └── List ├── api.ts ├── EditModal │ ├ ...