在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. mybatis 08: 返回主键值的insert操作 + 利用UUID获取字符串(了解)

    返回主键值的insert操作 应用背景 图示说明 在上述业务背景下,涉及两张数据表的关联操作:用户表 + 用户积分表 传统操作:在对用户表执行完插入语句后,再次查询该用户的uid,将该uid作为外键, ...

  2. Docker 03 镜像命令

    参考源 https://www.bilibili.com/video/BV1og4y1q7M4?spm_id_from=333.999.0.0 https://www.bilibili.com/vid ...

  3. 删除MySQL数据用户

    mysql删除用户的方法: 1.使用"drop user 用户名;"命令删除: 2.使用"delete from user where user='用户名' and ho ...

  4. 图解 Kafka 超高并发网络架构演进过程

    阅读本文大约需要 30 分钟. 大家好,我是 华仔, 又跟大家见面了. 上一篇作为专题系列的第一篇,我们深度剖析了关于 Kafka 存储架构设计的实现细节,今天开启第二篇,我们来深度剖析下「Kafka ...

  5. 【unity游戏入门】1 环境安装

    作者 罗芭Remoo 2021年9月24日 这一个系列随笔记录如何使用unity引擎从零开始开发游戏,软件版本均使用最新版本 有关unity的背景介绍可以通过unity官网https://unity. ...

  6. KingbaseES OOM 可能原因汇总

    背景 不久前,遇到过一个问题.KingbaseES数据库主机系统触发OOM现象是数据库进程被KILL, 数据库进入crash然后restart(when restart_after_crash=on) ...

  7. 一文搞懂mysql索引底层逻辑,干货满满!

    一.什么是索引 在mysql中,索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录.通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列即可 ...

  8. Dapr 的 gRPC组件 (又叫可插拔组件) 的提案

    Dapr 在1.9 版本中的提案,计划在 Dapr Runtime 中组件采用 外部 gRPC 组件: https://github.com/dapr/dapr/issues/3787 ,针对这个 g ...

  9. imread opencv

    ''' Mat cv::imread ( const String & filename, int flags = IMREAD_COLOR ) Python: retval = cv.imr ...

  10. kubernetes给容器生命周期设置操作事件

    Kubernetes支持预启动和预结束事件. Kubernetes在容器启动的时候发送预启动事件,在容器结束的时候发送预结束事件. 定义预启动和预结束事件操作 下面是Pod的配置文件: # cat l ...