场景介绍
vue中一个比较令人烦恼的事情是属性只能从父组件传递给子组件。这也就意味着当你想向嵌套层级比较深组件数据传递,只能由父组件传递给子组件,子组件再传递给孙子组件…像下面这样:
1 2 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
可以让孙子组件获取到父组件传给子组件但子组件没有用到的属性。
示例:
1 2 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属性外所有由父组件传递下来的属性。
1 2 3 4 5
| <grand-child-component v-bind="$attrs"/>
<div>我是孙子组件{{$attrs.age}}</div>
|
inheritAttrs
可以注意到,组件内未被注册的属性将作为普通html元素属性被渲染,在Vue2.4.0,可以在组件定义中添加inheritAttrs:false
,组件将不会把未被注册的props呈现为普通的HTML属性。
inheritAttrs
还有一个作用,看下边代码:
1 2 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
1 2 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
1 2 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~