vue3中$attrs的变化与inheritAttrs的使用详解

目录
  • 在vue3中的$attrs的变化
  • 在vue2中的$attrs
  • 父组件的属性直接渲染在根节点上

在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>

TM又又发现问题了

在浏览器中提示:[plugin:vite:vue] [@vue/compiler-sfc] <script> and <script setup> must have the same language type.
TM又又发现问题了。稳住,我可以的。在心里一直告诉自己,冷静点,我可以解决这个问题的。
先看看它提示  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的使用 的文章就介绍到这了,更多相关vue3 $attrs与inheritAttrs的使用 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue3 $attrs和inheritAttrs的用法说明

    目录 $attrs和inheritAttrs用法 在父组件app.vue中 子组件 myInput.vue 设置 inheritAttrs: true(默认) 子组件 myInput.vue 设置 inheritAttrs: false $attrs和inheritAttrs实例 $attrs和inheritAttrs用法 $attrs属性解释:包含了父作用域中不作为组件 props 或自定义事件的 attribute 绑定和事件.当一个组件没有声明任何prop 时,这里会包含所有父作用域的绑定

  • Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)

    当我们在书写 vue 组件的时候,也许可能会用到数据传递:将父组件的数据传递给子组件,有时候也需要通过子组件去事件去触发父组件的事件: 每当我们遇到这样的需求的时候,我们总是会想到有三种解决办法: 通过 props 的方式向子组件传递(父子组件) vuex 进行状态管理(父子组件和非父子组件) vuex 非父子组件的通信传递 Vue Event Bus ,使用Vue的实例,实现事件的监听和发布,实现组件之间的传递. 后来再逛社区的时候我又发现了还有第四种传递方式, inheritAttrs +

  • Vue vm.$attrs使用场景详解

    1.vm.$attrs简介 首先我们来看下vue官方对vm.$attrs的介绍: 包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外).当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件--在创建更高层次的组件时非常有用. 猛一看有点看不明白.... 2.场景介绍 vue中一个比较令人烦恼的事情是属性只能从父组件传递给子组件

  • Vue中inheritAttrs的使用实例详解

    今天举一个例子解释一下inheritAttrs的使用 先看代码 <body> <div id="app" class="vueclass"> <my-com title="标题" wx-attr1="未定义属性1" wx-attr2="未定义属性2"></my-com> </div> <script type="text/javas

  • vue $attrs的使用全面解析

    目录 $attrs的使用vue 以下是$attrs的使用示例 1.父组件(Father.vue) 2.儿子组件(Child.vue) 3.孙子组件(GrandChild.vue) $attrs到底是什么? 先来看看官方文档给的定义 $attrs的使用vue $attrs是在vue的2.40版本以上添加的. 项目中有多层组件传参可以使用$attrs,可以使代码更加美观,更加简洁,维护代码的时候更方便.如果使用普通的父子组件传参prop和$emit,$on会很繁琐:如果使用vuex会大材小用,只是在

  • Vue v2.4中新增的$attrs及$listeners属性使用教程

    前言 多级组件嵌套需要传递数据时,通常使用的方法是通过vuex.如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点杀鸡用牛刀.Vue 2.4 版本提供了另一种方法,使用 v-bind="$attrs", 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用.之所以要提到这两个属性,是因为两者的出现使得组件之间跨组件的通信在不依赖 vuex 和事件总线的情况下变得简洁,业务清晰. 首先分析以下应用场景: A 组件与 B

  • vue3中$attrs的变化与inheritAttrs的使用详解

    目录 在vue3中的$attrs的变化 在vue2中的$attrs 父组件的属性直接渲染在根节点上 在vue3中的$attrs的变化 $listeners已被删除合并到$attrs中. $attrs现在包括class和style属性. 也就是说在vue3中$listeners不存在了.vue2中$listeners是单独存在的. 在vue3 $attrs包括class和style属性, vue2中 $attrs 不包含class和style属性. 在vue2中的$attrs 在Vue 2中,at

  • Vue3响应式方案及ref reactive的区别详解

    目录 一.前言 二.新的方案 1. 缘由 2. Proxy 和 Reflect 1) Proxy 2) Reflect 3. reactive 1) createReactiveObject() 函数 2) mutableHandlers() 函数 -> 对象类型的 handlers 3) mutableInstrumentations() 函数 -> Map Set等类型的 handlers 4. ref 1) createRef() 2) toReactive() 3)proxyRefs(

  • 对angular 监控数据模型变化的事件方法$watch详解

    $watch简单使用 $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEquality); 每个参数的说明如下: watchExpression:监听的对象,它可以是一个angular表达式如'name',或函数如function(){return $scope.name}. listener:当watchExpression变化时会被调用的函数或者表达式,它接收3个参数:n

  • vue3响应式Object代理对象的读取示例详解

    目录 正文 读取属性 xx in obj for ... in 正文 从这一章开始,作者将更新深入的讲解响应式,尤其是vue3响应式的具体的实现.其实在前面一章,如果你仔细阅读,你是可以实现一个简单的响应式函数的,类似于@vue/reactive,当然那只是个demo,是个玩具,我能不能在生产环境上去使用的,它差了太多功能和边界条件. 现在,我们才是真正的深入@vue/reactive. 在vue中,obj.a是一个读取操作,但是仔细想来,读取这个操作很宽泛. obj.a // 访问一个属性 '

  • vue2从数据变化到视图变化之diff算法图文详解

    目录 引言 1.isUndef(oldStartVnode) 2.isUndef(oldEndVnode) 3.sameVnode(oldStartVnode, newStartVnode) 4.sameVnode(oldEndVnode, newEndVnode) 5.sameVnode(oldStartVnode, newEndVnode) 6.sameVnode(oldEndVnode, newStartVnode) 7.如果以上都不满足 小结 引言 vue数据的渲染会引入视图的重新渲染.

  • vue3.2自定义弹窗组件结合函数式调用示例详解

    目录 前言 手写弹窗组件 组件调用 函数式调用 如何使用 含样式完整源码 效果图 前言 涉及的vue3知识点/API,createApp defineProps defineEmits <script setup> v-model <script setup> 就是 setup 语法糖 defineProps 和 props 用法差不多 defineEmits 声明可向其父组件触发的事件 手写弹窗组件 很简单的弹窗组件,支持设置标题 <script setup> def

  • Vue3从0搭建Vite打包组件库使用详解

    目录 打包配置 声明文件 打包配置 本篇文章将介绍如何使用 vite 打包我们的组件库,同时告诉大家如何使用插件让打包后的文件自动生成声明文件(*.d.ts) vite 专门提供了库模式的打包方式,配置其实非常简单,首先全局安装 vite 以及@vitejs/plugin-vue pnpm add vite @vitejs/plugin-vue -D -w 在 components 文件下新建vite.config.ts配置文件 import { defineConfig } from "vit

  • vue3自定义插件的作用场景及使用示例详解

    目录 插件的作用场景 插件的定义(注册) 插件的安装 插件的使用 插件中的Provide/inject 插件的作用场景 在vue2的插件那篇文章我们介绍过插件其实就是vue的增强功能.通常来为vue添加全局功能的.在vue3中插件的功能也是一样的,只是它们在定义上有所不同. 通过app.component()和app.directive()注册一到多个全局组件或自定义指令 通过app.provide()使一个资源可被注入进整个应用 向app.config.globalProperties中添加一

  • vue3.0中的watch侦听器实例详解

    目录 前言 侦听器和计算属性的区别 vue3如何使用watch呢? 基本使用 监听多个响应式数据 侦听reactive定义的响应式数据 监听reactive定义的响应式数据的某一个属性 配置选项用法 总结 前言 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器.这就是为什么 Vue 通过watch选项提供了一个更通用的方法,来响应数据的变化.当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的. 侦听器和计算属性的区别 计算属性里不可以做异步操作,侦听器可以做异步操作

  • 基于Vue3+TypeScript的全局对象的注入和使用详解

    目录 1.Vue2的全局挂载 2.Vue3+TypeScript的全局挂载 3.Vue3+TypeScript的全局挂载的对象接口定义 刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局对象的注入和使用.我们知道在Vue2中全局注入一个全局变量使用protoType的方式,很方便的就注入了,而Vue3则不能通过这种方式直接使用,而是显得复杂一些,不过全局变量的

随机推荐