vue3 $attrs和inheritAttrs的用法说明

目录
  • $attrs和inheritAttrs用法
    • 在父组件app.vue中
    • 子组件 myInput.vue 设置 inheritAttrs: true(默认)
    • 子组件 myInput.vue 设置 inheritAttrs: false
  • $attrs和inheritAttrs实例

$attrs和inheritAttrs用法

  • $attrs属性解释:包含了父作用域中不作为组件 props 或自定义事件的 attribute 绑定和事件。当一个组件没有声明任何prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——这在创建高阶的组件时会非常有用。
  • inheritAttrs属性解释:如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false

可能不是很好理解,我们可以举个例子来验证一下。

在父组件app.vue中

<template>
  <div>
    <MyInput type="text" placeholder="输入用户名" v-model="state.text" />
    <MyInput type="password" placeholder="输入密码"  v-model="state.pass"  />
  </div>
</template>
<script setup>
import MyInput from "@/components/myInput.vue";
import { reactive } from "vue";
const state = reactive({
  text: "",
  pass: "",
});
</script>

子组件 myInput.vue 设置 inheritAttrs: true(默认)

<template>
  <div class="input">
    <input v-bind="$attrs" v-model="modelValue" />
  </div>
</template>
<script>
export default {
  props: {
    modelValue: [String, Number],
  },
};
</script>

子组件 myInput.vue 设置 inheritAttrs: false

<template>
  <div class="input">
    <input v-bind="$attrs" v-model="modelValue"/>
  </div>
</template>
<script>
export default {
  inheritAttrs: false,
  props: {
    modelValue: [String, Number],
  },
};
</script>

小结:

由上述例子可以看出,子组件的props中未注册父组件传递过来的属性。

  • 当设置inheritAttrs:true时,子组件的顶层标签元素中会渲染出父组件传递过来的属性(例如:type="text"等)
  • 当设置inheritAttrs: false时,子组件的顶层标签元素中不会渲染出父组件传递过来的属性
  • 不管inheritAttrs为true或者false,子组件中都能通过$attrs属性获取到父组件中传递过来的属性。

$attrs和inheritAttrs实例

官网的文档简短而又不清晰,实在是看不懂,只好自己找代码验证来看看是什么意思:

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.1.5/vue.global.js"></script>
</head>
 
<body>
    <div id="app">
        <father :v1="'value1'" :v2="'value2'" :v3="'value3'"></father>
    </div>
</body>
 
</html>
<script>
const app = Vue.createApp({
    data() {
        return {}
    },
})
app.component('father', {
 // inheritAttrs: false,
    props: ['v1'],
    template: ` <div><p>v1 is {{v1}}</p>
		  <son v-bind='$attrs' :some="1"></son>
	       </div>`,
    created() {
        console.log('father:', this.$attrs)
    }
})
app.component('son', {
    // inheritAttrs: false,
    props: ['v2'],
    template: `<div><p>v2 is {{v2}}</p>
                     <grandSon v-bind='$attrs'></grandSon>
              </div>`,
    created() {
        console.log('son:', this.$attrs)
    }
})
app.component('grandSon', {
    props: ['v3'],
    template: `<p>v3 is {{v3}}</p>`,
    created() {
        console.log('grandSon:', this.$attrs)
    }
})
app.mount('#app')
</script>

页面显示的结果:

v1 is value1

v2 is value2

v3 is value3

页面源代码:

<div id="app" data-v-app="">
   <div v2="value2" v3="value3"> <!-- 这是father -->
      <p>v1 is value1</p>
      <div v3="value3" some="1">  <!-- 这是 son-->
          <p>v2 is value2</p>
           <p some="1">v3 is value3</p>  <!-- 这是 grandSon -->
      </div>
   </div>
</div>

控制台打印是当前组件的$attrs:

father: Proxy {v2: "value2", v3: "value3", __vInternal: 1}

son: Proxy {v3: "value3", some: 1, __vInternal: 1}

grandSon: Proxy {some: 1, __vInternal: 1}

首选,father组件被传入了3个值,但是实际使用props接收的只有v1,v2和v3作为attributes在DOM里面渲染了。

上图的devtool 也可以说明,另外就是控制台也同时证明了。

同样son组件只是接收v2作为prop:

grandSon组件只是接收v3作为prop

father prop:v1,attributes: v2,v3

son prop:v2 ,attributes:v3,some

grandSon prop:v3,,attributes: some

发现无论是father传入的3个值v1,v2,v3还是son又传入的值':some=1',

只要不被prop传入下一层组件,那么一定是在下一层组件的$attrs,也就是说不被作为prop的值会传入下一个组件作为attrs的一员。一个组件的attrs由父组件传递以及自己自带的组合而成。

上面说的是$attrs,那么inheritAttrs则说的是attrs继承,这里的继承是控制DOM渲染,不继承也就是不渲染了,但是实际还是存在这个attrs的。

`inheritAttrs`属性默认是true,所以能看到上面的结论,attrs会往下传,当设置为false的时候就不会在DOM渲染从上一层继承来的attrs。

修改一下代码:

app.component('father', {
   inheritAttrs: false,    // 不继承
    props: ['v1'],
    template: ` <div><p>v1 is {{v1}}</p>
		  <son v-bind='$attrs' :some="1"></son>
	       </div>`,
    created() {
        console.log('father:', this.$attrs)
    }
})

father组件这不继承attrs,控制台的打印没变:

father: Proxy {v2: "value2", v3: "value3", __vInternal: 1}

son: Proxy {v3: "value3", some: 1, __vInternal: 1}

grandSon: Proxy {some: 1, __vInternal: 1}

devtool这里依然可以看到attrs

但是看源代码:

<div id="app" data-v-app="">
  <div>                          <!-- 这里是 father --> <!-- 看这行 -->
    <p>v1 is value1</p>
    <div v3="value3" some="1">     <!-- 这里是 son-->
      <p>v2 is value2</p>
      <p some="1">v3 is value3</p>   <!-- 这里是 grandSon-->
      </div>
    </div>
</div>

DOM渲染里面的v2,v3 attrs都不存在了。

所以综合总结一下:

$attrs就是给组件传值排除了作为prop的那部分(比如father的v2,v3),包括了(class,id)inheritAttrs只是用来控制attrs是否在DOM中渲染。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Vue中$props、$attrs和$listeners的使用方法

    目录 背景 一.文档描述 二.具体使用 三.总结 背景 现在我们来讨论一种情况,父组件与孙子组件怎么通信,我们有多少种解决方案? 我们使用VueX来进行数据管理,但是如果项目中多个组件共享状态比较少,项目比较小,并且全局状态比较少,那使用VueX来实现该功能,并没有发挥出VueX的威力. 使用B来做中转站,当A组件需要把信息传给C组件时,B接受A组件的信息,然后利用属性传给C组件, 这是一种解决方案,但是如果嵌套的组件过多,会导致代码繁琐,代码维护比较困难;如果C中状态的改变需要传递给A, 使用

  • 在vue中使用inheritAttrs实现组件的扩展性介绍

    1.首先我们创建一个input组件 <template> <div class="inputCom-wrap"> <input v-bind="$attrs" /> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent

  • Vue $attrs & inheritAttr实现button禁用效果案例

    components/Button.vue <template> <div> <button :disabled="$attrs.disabled">点击</button> </div> </template> <script> export default { inheritAttrs: false, } </script> <style scoped> </style&

  • 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

  • vue3 $attrs和inheritAttrs的用法说明

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

  • 浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用

    vue父子组件之间的传值我们都知道使用props和emit,但是祖孙之间的传值在以前,我们都需要子辈作为中间人,当祖辈有值要传递给孙辈时,需要子辈作为中间人把值传递给孙辈,当孙辈想要改变祖辈的值时,需要先emit子辈的方法,然后子辈再emit父辈的方法从而改变祖辈的值,如果是多级组件嵌套的话,那么祖孙辈之间传值,就会变得非常的繁琐,为了解决这个需求,vue2.4版本产生了$attrs,$listeners,inheritAttrs这三个属性. vm.$attrs 官方API vm.$attrs

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

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

  • 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

  • vue $attrs和$listeners的使用与区别

    首先让我们看一下这张图,表示了一个多级关联的组件嵌套 为什么要用$attrs 和 $listeners 先让我们来想一种情况,就是组件A跟组件C怎么通信,我们可以有多少中解决方案? 看到这种情况,大多数人应该会想到用vuex来进行数据通信吧,但是如果项目中多个组件中的共享状态很少,且项目比较小,全局数据通信也很少,那我们用vuex来实现这个功能,就感觉有点杀鸡用牛刀了 我们可以使用组件B来做通信的中转站,当组件A需要把数据传到组件C时,组件A通过props将数据传给组件B,然后组件B再用prop

  • 在Vue使用$attrs实现构建高级组件

    目录 什么是 $attrs attrs V3 vs $attrs V2 事例 添加一些属性 添加标题和值 $attrs 救场 inheritAttrs: false 这节课,我们来看下 Vue3 中的 $attrs 属性.首先,我们会介绍它的用途以及它的实现与 Vue2 有哪些不两同点,并通过事例来加深对它的理解. 真正理解了 $attrs 属性有助于我们构建易于使用和可扩展的高级组件 什么是 $attrs 对 $attrs 定义, Vue2 与 Vue3 是不一样的,这里我们主要来介绍 Vue

  • Android实现简单底部导航栏 Android仿微信滑动切换效果

    Android仿微信滑动切换最终实现效果: 大体思路: 1. 主要使用两个自定义View配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标; 2. 底部导航栏的设置方法类似于TabLayout的关联,View需要创建关联方法,用来关联VIewPager; 3. 通过关联方法获取ViewPager实例后,根据ViewPager页面数创建底部导航栏的图标按钮; 代码实现: 1. 新建第一个自定义View, 图标 + 文字 的底部按钮; /** * 自定义控件

  • vue切换菜单取消未完成接口请求的案例

    在做别的功能时 console里面总会报别的菜单接口里的错 看的很心烦 于是想优化一下 就有了这篇文章 在切换菜单的时候取消所有未完成接口的请求 1.找到自己的请求拦截器 重点是 config.cancelToken = global.store.source.token; http.interceptors.request.use(config => { config.cancelToken = global.store.source.token; return config }, err =

  • vue3.0 项目搭建和使用流程

    最近在重构一个老项目,领导要求使用新的技术栈.好吧,是时候秀一波我新学的vue3.0了. 不多bb,开始我的表演...(以下只是我自己个人的理解和使用习惯,仅供参考哦) 一:项目搭建 1. 可以自己配置vite,但是为了节省时间,我就使用脚手架直接搭建.(有兴趣可以研究一下vite,还是很香的) 2. 项目生成:iTerm下: vue create myproject 之后根据自己的要求选择不同的配置 选择我们需要的3.x 之后按照要求配置一下router,已经pack.json ... 然后n

随机推荐