在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. 3. 安装部署MGR集群 | 深入浅出MGR

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 目录 1. 安装准备 2. 初始化MySQL Server 3. 初始化MGR第一个节点 4. 继续设置另外两个节点 5. ...

  2. Windows下安装新硬盘

    首先,插上一个硬盘然后开机,会发现"我的电脑/此电脑"里面并没有这个硬盘,这是因为此时硬盘还没初始化和分区,分完区后每个分区会被作为一个逻辑盘显示在里面.那么接下来就是过程. Wi ...

  3. Luogu4111 [HEOI2015]小Z的房间 (矩阵树,辗转相除高斯消元)

    除法不能用于同余系,要辗转相除.注意不能加入柱子到矩阵. #include <iostream> #include <cstdio> #include <cstring& ...

  4. SvelteUI:运用svelte3构建的网页版UI组件库(升级版)

    距离上次分享的svelte-ui 1.0已经一月有余,这次带来全新升级完整版svelte-ui 2.0. 这次优化并新增15+个组件.在开发之初借鉴了element-ui组件库,所以在组件结构及语法上 ...

  5. Dart 异步编程(三):详细认识

    基本概念 普通任务按照顺序执行:异步任务将在未来的某个时间执行. 实际演示 void main() { // waitFuture 函数是一个异步函数,阻塞会发生在函数内部 waitFuture(); ...

  6. 前端架构-分层而治,铁打的MV流水的C

    大家好,我是Eluxjs的作者,Eluxjs是一套基于"微模块"和"模型驱动"的跨平台.跨框架『同构方案』,欢迎了解... 文前声明,以下推断和结论纯属个人探索 ...

  7. java基础———标识符和关键字

    标识符以字母开头  (A-Z)或(a-z)    美元符($)     下划线(_) 不能以关键字作为变量名或者方法名 标识符大小写不能混淆 可以中文(不建议) 常用的关键字

  8. ClickHouse与Elasticsearch压测实践

    1 需求分析 1.1 分析压测对象 1)什么是ClickHouse 和Elasticsearch ClickHouse 是一个真正的列式数据库管理系统(DBMS).在 ClickHouse 中,数据始 ...

  9. KingbaseES timestamp 和 timestamptz 差异比较

    KingbaseES 提供两种存储时间戳的数据类型: 不带时区的 TIMESTAMP 和带时区的 TIMESTAMPTZ. TIMESTAMP 数据类型可以同时存储日期和时间,但它不存储时区.这意味着 ...

  10. C++ 由快排学习到的的随机数等知识

    起: 力扣的912题 数组排序 ,想着先用快速排序来写写,在实际用c++编写的时候,有一些之前没注意到的细节问题造成了一些麻烦. 912. 排序数组 - 力扣(LeetCode) 快排思想 每次以数组 ...