场景介绍
vue中一个比较令人烦恼的事情是属性只能从父组件传递给子组件。这也就意味着当你想向嵌套层级比较深组件数据传递,只能由父组件传递给子组件,子组件再传递给孙子组件…像下面这样:
| 12
 3
 4
 5
 6
 7
 8
 
 | <parent-component :passdown="passdown"> // 父组件
 <child-component :passdown="passdown"> // 子组件
 
 <grand-child-component :passdown="passdown"> // 孙子组件
 
 ....
 
 
 | 
就这样一层一层的往下传递passdown这个变量,最后才能用。
vm.$attrs
这时候出现了vm.$attrs,好家伙,直接起飞。$attrs可以让孙子组件获取到父组件传给子组件但子组件没有用到的属性。
示例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | <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这个属性,massgae属性我么是没有用的,于是this.$attrs,就可以获取到massgae:'message111'

即子组件绑定了”$attrs”,孙子组件就能获取到除了name属性外所有由父组件传递下来的属性。
| 12
 3
 4
 5
 
 | <grand-child-component v-bind="$attrs"/>
 
 
 <div>我是孙子组件{{$attrs.age}}</div>
 
 | 
inheritAttrs
可以注意到,组件内未被注册的属性将作为普通html元素属性被渲染,在Vue2.4.0,可以在组件定义中添加inheritAttrs:false,组件将不会把未被注册的props呈现为普通的HTML属性。
inheritAttrs还有一个作用,看下边代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | <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>
 
 | 
上面的父组件传递了type="text",子组件里input 上type="number"也会被渲染成``type=”text”`,这显然不是我们想要的结果!
需求:我需要input 上type=”number”类型不变,但是我还是要取到父组件的type=”text”的值,这时候,你就需要在子组件里加上inheritAttrs:false
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | components:{'childcom':{
 inheritAttrs:false, // 这里
 props:['name','age'],
 template:`<input type="number" style="border:1px solid blue">`,
 created () {
 console.log(this.$attrs.type)
 }
 }
 }
 
 | 
$listeners
父组件-子组件-孙子组件,假如我想在孙子组件更改父组件的值,这里有一种方法是使用$listeners
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 
 | <template><div>
 <childcom :name="name" :age="age" :sex="sex" @testChangeName="changeName"/>
 </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可以让你在孙子组件改变父组件的值,So easy~