一.attrs
1.场景
多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点杀鸡用牛刀。Vue 2.4 版本提供了另一种方法,使用 v-bind='$attrs'
, 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用。之所以要提到这两个属性,是因为两者的出现使得组件之间跨组件的通信在不依赖 vuex 和事件总线的情况下变得简洁,业务清晰。
2.官方文档
vue官方介绍,我是没有理解.连接
3.栗子(父子)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| //父组件里 <template> <div id="app"> //子组件 <child1 :age="age" :name="name"></child1> </div> </template> <script> export default { data () { return { age:27, name:'hjai' }; } } </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| //子组件里 <template> <div> <p>我是子组件</p> <p>props: {{age}}</p> <p>$attrs: {{$attrs}}</p> </div> </template> <script> export default { props: ['age'] } </script>
//props:25 //$attrs:{name:'hjai'}
|
看了实例,就大概了解官方所说的‘包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)’.
我的理解就是:父组件要传的值(age,name),在子组件中,没用props注册.在子组件中包含在$attrs
中,以object
的形式访问到.
5.标题不是爷孙通信吗.
不啰嗦,直接上代码.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| //组件child2 <template> <div> <p>我是子组件</p> <p>props: {{age}}</p> <p>$attrs: {{$attrs}}</p> //我在这呢 <child1 v-bind="$attrs"></child1> </div> </template> <script> export default { props: ['age'] } </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| //孙子组件(child2) <template> <div> <p>我是孙组件</p> <p>props: {{name}}</p> <p>$attrs: {{$attrs}}</p> </div> </template>
<script> export default { props: ['name'], data () { return {}; }, inheritAttrs: false }; </script> //props:hjai //$attrs:{}
|
这样在孙组件中,就可以获得爷组件中的要传递的值.
二.inheritAttrs
这有什么什么,干什么用.别着急.
此时请查看子组件的dom元素,是不是发现了多了 name='hjai'
在dom上面.
组件内未被注册的属性将作为普通html元素属性被渲染.
不想他渲染怎么办,我们在子组件里设置 inheritAttrs: false
.
再看dom是不是就没有了,没有注册props
的属性没有显示出来.
三.listeners
1.官方文档:
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners”
传入内部组件——在创建更高层次的组件时非常有用.
2.栗子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| //书接上文,在父组件中添加个onTest事件. <template> <div id="app"> //子组件 <child1 :age="age" :name="name" @test='onTest'></child1> </div> </template> <script> export default { data () { return { age:27, name:'hjai' }; }, methods: { onTest($data){ console.log($data); } } } </script> //'哈哈哈'
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| //子组件(child1) <template> <div> <p>我是子组件</p> <p>props: {{age}}</p> <p>$attrs: {{$attrs}}</p> //我在这呢 <child1 v-bind="$attrs" v-on="$listeners"></child1> </div> </template> <script> export default { props: ['age'] } </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| //孙子组件(child2) <template> <div> <p>我是孙组件</p> <p>props: {{name}}</p> <p>$attrs: {{$attrs}}</p> </div> </template>
<script> export default { props: ['name'], data () { return {}; }, inheritAttrs: false, mouted(){ this.$emit("test",'哈哈哈'); } }; </script>
|
孙组件中能直接触发test的原因在于 子组件调用孙组件时 使用 v-on 绑定了$listeners 属性.