前言
今天在开发的时候,发现同事用到了$attrs
和$listeners
,因为此前本人用的很少,所以就去研究了一下,总的来说这两个api就是用来进行组件之间通信的,只不过不用像props和$emit传值t通信那样繁琐,缺点就是不好维护,可读性比较低,因此我们在项目中用的比较少,如果需要跨多个组件通信也会选择Vuex
主要内容
- 先来看
$attrs
和$listeners
的定义在Vue文档中:vm.$attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
- 再来写个Demo
- App.vue
<template> <div id="app"> <Child1 :words1="text1" :words2="text2" :words3="text3" v-on:event1="goEvent1" v-on:event2="goEvent2"></Child1> </div> </template> <script> import Child1 from "./components/Child1" export default { name: "App", data() { return { text1: 1, text2: 2, text3: 3 } }, methods: { goEvent1() { console.log("child 提交成功") }, goEvent2(value) { console.log(value) } }, components: { Child1, } } </script> <style> html, body { height: 100%; } #app { height: 100%; } </style>
- Child1.vue
<template> <div class="mainWrapper"> <p>props: {{words1}}</p> <p>$attrs: {{$attrs}}</p> <button @click="submit()">提交</button> <hr> <child2 v-bind="$attrs" v-on="$listeners"></child2> <!-- 通过$listeners将父作用域中的v-on事件监听器,传入child2,使得child2可以获取到app中的事件 --> </div> </template> <script> import Child2 from "./Child2" export default { name: "Child1", props: ["words1"], data() { return {} }, inheritAttrs: true, components: { Child2 }, methods: { submit() { this.$emit("event1", "child1 提交事件") } } } </script> <style scoped> .mainWrapper { height: 100px; } </style>
- Child2.vue
<template> <div> <div class="child-2"> <p>props: {{words2}}</p> <p>$attrs: {{$attrs}}</p> <input v-model="inputValue" name="" id="" @input="goInput"> </div> </div> </template> <script> export default { name: 'Child2', props: ['words2'], data() { return { inputValue: '' }; }, inheritAttrs: false, mounted() { }, methods: { goInput () { this.$emit('event2', this.inputValue); } } } </script>
- 效果
- 可以看到父组件App.vue中通过v-bind给Child1传递了三个值,在子组件中未被Props接收的值都在
$attrs
中,其也可以通过v-bind将值传递给Child1的内部组件Child2,同时也可以使用$listeners
将父作用域中的v-on事件监听器,传入child2
- 可以看到父组件App.vue中通过v-bind给Child1传递了三个值,在子组件中未被Props接收的值都在
- inheritAttrs 属性以及作用
- 当一个组件设置了inheritAttrs: false后(默认为true),那么该组件的非props属性(即未被props接收的属性)将不会在组件根节点上生成html属性,以为为对比图
inheritAttrs:false
inheritAttrs:true