Vue2.4.0新增inheritAttrs,attrs详解,补充说明$listener

场景介绍

vue中的属性绑定只能是父组件传递给子组件。当你有这样的需求:你想向嵌套层级比较深的组件传递数据的时候,只能由父组件传递给子组件,子组件再传递给孙子组件,例如:

<parent-component :passdown="passdown">

<child-component :passdown="passdown">

<grand-child-component :passdown="passdown">

....

就这样一层一层的往下传递passdown这个变量,最后才能用{{passdown}}。

当我们传递几个或10几个嵌套级组件的情况来看,我们就要在每个组件中不停地props,每个必须写很多遍,让代码看起来很累赘,那有没有什么更简便的方法呢?答案是肯定的,

  • 通过vuex通信,
  • 通过inheritAttrs,以及实例属性$attrs
<template>
  <div class="home">
    <mytest  :title="title" :massgae="massgae"></mytest>
  </div>
</template>
<script>
export default {
  name: 'home',
  data () {
    return {
      title:'title1111',
      massgae:'message111'
    }
  },
  components:{
    'mytest':{
      template:`<div>这是个h1标题{{title}}</div>`,
      props:['title'],
      data(){
        return{
          mag:'111'
        }
      },
      created:function(){
        console.log(this.$attrs)//注意这里
      }
    }
  }
}
</script>

上边的代码当中,我们只在子组件中用了title这个属性,message属性是没用到的,那么下面浏览器渲染出来是什么样呢?
如下图:
在这里插入图片描述

我们看到: 组件内未被注册(未在props中注册,在本组件中不需要用到的属性)的属性将作为普通html元素属性被渲染,但是我们又向要向下传递,又不想要未被注册的属性作为普通html元素属性被渲染,那还有什么方法呢?在Vue2.4.0中,可以在组件定义中添加inheritAttrs:false,组件将不会把未被注册的属性呈现为普通的HTML属性。但是在组件中我们可以通过其$attrs可以获取到没有注册的属性。

components:{
    'mytest':{
      template:`<div>这是个h1标题{{title}}</div>`,
      props:['title'],
      inheritAttrs: false,
      data(){
        return{
          mag:'111'
        }
      },
      created:function(){
        console.log(this.$attrs)//注意这里
      }
    }
    ```
    渲染效果:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/2019112618072475.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqbTEzMjQ5NDI1Mjgw,size_16,color_FFFFFF,t_70)

## 补充:说一下$attrs的使用
有一个页面有父组件,子组件,孙子组件构成,如下:

<template>
    <div style="padding:50px;">
        <childcom :name="name" :age="age" :sex="sex"></childcom>
    </div>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'张三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            template:`<div>
                <div>{{name}}</div>
                <grandcom v-bind="$attrs"></grandcom>
            </div>`,
            props:['name'],
            components: {
                'grandcom':{
                    template:`<div>{{$attrs}}</div>`,
                }
            }
        }
    }
}
</script>

效果图:

在这里插入图片描述
说明:如果attrs被绑定在子组件childcom上,我们就可以在孙子组件grandcom中获取到this.KaTeX parse error: Expected '}', got 'EOF' at end of input: attrs的值。这个{{attrs}}的值只是父组件中传递下来的props(除了在子组件childcom组件中props声明的)

特别注意:记住孙子组件grandcom里获取到this. a t t r s 的 值 是 除 了 子 组 件 c h i l d c o m 声 明 的 元 素 ! 记 住 是 除 了 子 组 件 c h i l d c o m 声 明 的 元 素 ! 例 如 上 面 的 代 码 我 在 子 组 件 c h i l d c o m 组 件 的 p r o p s 里 声 明 了 n a m e , 那 么 我 在 孙 子 组 件 g r a n d c o m 里 获 取 到 的 attrs的值是除了子组件childcom声明的元素!记住是除了子组件childcom声明的元素!例如上面的代码我在子组件childcom组件的props里声明了name,那么我在孙子组件grandcom里获取到的 attrschildcomchildcomchildcompropsnamegrandcomattrs就不包含name属性,那么this.$attrs = { ‘age’:‘30’, ‘sex’:‘男’}。

补充以下:inheritAttrs属性

  • 关于inheritAttrs这个属性跟获取到$attrs的值没有关系,inheritAttrs通常在编写基础组件时候会用到。
  • 注意:这个选项不影响 class 和 style 绑定。
  • 在Vue2.4.0之前版本,组件内未被注册的属性将作为普通html元素属性被渲染。

inheritAttrs到底有啥用?到底用在哪里?

<template>
    <childcom :name="name" :age="age" type="text"></childcom>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'张三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            props:['name','age'],
            template:`<input type="number" style="border:1px solid blue">`,
        }
    }
}
</script>

上面代码你觉得input上会怎么显示? 父组件传递了type=“text”,子组件里input 上type=“number”,那渲染到页面会是什么样?渲染图如下:
在这里插入图片描述
看到没,父组件传递的type="text"覆盖了input 上type=“number”,这岂不是把我的input数据类型都给改变了,这岂不是有问题,这不是我想要的!!!!看到这里明白了吗?回头去体会下上面官网的原话!!!

需求:我需要input 上type="number"类型不变,但是我还是要取到父组件的type="text"的值,那么代码如下:

<template>
    <childcom :name="name" :age="age" type="text"></childcom>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'张三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            inheritAttrs:false,
            props:['name','age'],
            template:`<input type="number" style="border:1px solid blue">`,
            created () {
                console.log(this.$attrs.type)
            }
        }
    }
}
</script>

页面渲染图:
在这里插入图片描述

到这,我想大家都明白了inheritAttrs的作用了吧。默认情况下vue会把父作用域的不被认作 props 的特性绑定 且作为普通的 HTML 特性应用在子组件的根元素上。绑定就绑定,显示就显示,没啥大不了的,但是怕就怕遇到一些特殊的,就比如上面的input的情况,这个时候inheritAttrs:false的作用就出来啦。

补充一下:$listeners

父组件-子组件-孙子组件,,,,现在我要你在孙子组件里改变父组件的值,怎么改?有很多方法啦,但是$listeners给我们提供了一个新的思路。话不多说,直接上代码

<template>
    <div>
        <childcom :name="name" :age="age" :sex="sex" @testChangeName="changeName"></childcom>
    </div>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'张三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            props:['name'],
            template:`<div>
                <div>我是子组件   {{name}}</div>
                <grandcom v-bind="$attrs" v-on="$listeners"></grandcom>
            </div>`,
           
            components: {
                'grandcom':{
                    template:`<div>我是孙子组件-------<button @click="grandChangeName">改变名字</button></div>`,
                    methods:{
                        grandChangeName(){
                           this.$emit('testChangeName','kkkkkk')
                        }
                    }
                }
            }
        }
    },
    methods:{
        changeName(val){
            this.name = val
        }
    }
}
</script>

页面渲染如下:
在这里插入图片描述
$listeners可以让你在孙子组件改变父组件的值,是不是很方便…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值