vue中的$attrs和$listeners

文章类型:Vue

发布者:hp

发布时间:2022-08-10

在使用vue框架中,经常会用到父子孙等多层次组件传参,如果采用props一层一层接收,就过于繁琐,官方提供$attrs和 $listeners来进行跨组件传参和方法处理

vue2版本

$attrs

主要是将父组件传过来的数据进行收集 ,如果props里面做了接收,那么$attrs则只收集没有接收的参数

inheritAttrs: false/ture,这个主要是是否将传递的参数显示在dom节点属性上 ,只会显示props没有接收的参数,如果props接收过的,则不在显示到节点

true:默认的显示

inheritAttrs: true,

false :则不显示

inheritAttrs: false,



<template>
<div id="app">
<div>vue2</div>
<father :info=info :info2=info2 v-on:eventOne="methodOne" ></father>
<button @click="modityInfo()">修改info值</button>
<button @click="modityInfo2()">修改info2值</button>
</div>
</template>

<script>
import father from './components/father.vue'
export default {
name: 'App',
data(){
return{
info:{
name:'张三',
id:1
            },
info2:{
name:'李四',
id:2
            }
        }
    },
components:{
father
    },

我们从祖组件传递两个props对象 info 和info2

<template>
<div>
<p>Father组件</p>
<son v-bind="$attrs" v-on="$listeners" ></son>
<button @click="sendFather()">发送给父组件数据</button>
</div>
</template>

<script>
import son from './son.vue'
export default {
name:'FatherOne',
inheritAttrs: false,
// props:['info'],
mounted() {
console.log(this.$attrs)
// console.log(this.$listeners)

        },

组件不适用props接收,则$attrs接收到全部参数

如果使用props接收全部或者某个,则$attrs就会排除接收的后参数,

 export default {
name:'FatherOne',
inheritAttrs: false,
props:['info'],
mounted() {
console.log(this.$attrs)
// console.log(this.$listeners)

        },

如果要继续进行孙组件等等,则需要继续传递$attrs,

<son v-bind="$attrs" v-on="$listeners" ></son>

接收原理一样

<template>
<div>
<p>Son组件组件</p>
<button @click="sendAnce()">发送给祖组件数据</button>
</div>
</template>

<script>
export default{
name:'SonTwo',
data(){
return{

            }
        },
props:{
info:{
default:()=>({})
            },
info2:{
default:()=>({})
            }
        },
watch:{
info:{
handler(val){
console.log("监听info的值")
console.log(val)
                },
deep:true,
immediate:true
            },
info2:{
handler(val){
console.log("监听info2的值")
console.log(val)
                },
deep:true,
immediate:true
            }
        },

孙组件可采用props接收或者赋值使用

$listeners

官方的描述是事件监听器,主要采用v-on="$listeners",传入内部组件,

个人的理解,类似于中间件,把父级的方法传递给子孙组件使用,由他们进行一个触发,把参数通过函数调用或者$emit方式调用把数据传回给父组件

 <father :info=info :info2=info2 v-on:eventOne="methodOne" @senddata="getSenddata" ></father>

最外层组件传递两个方法,on:eventOne和senddata

mounted() {
// console.log(this.$attrs)
console.log(this.$listeners)

        },

父组件接收到传递过来的方法

<template>
<div>
<p>Father组件</p>
<son v-bind="$attrs" v-on="$listeners" ></son>
<button @click="sendFather()">发送给父组件数据</button>
</div>
</template>

<script>
import son from './son.vue'
export default {
name:'FatherOne',
inheritAttrs: true,

mounted() {
// console.log(this.$attrs)
console.log(this.$listeners)

        },
components:{
son
        },
methods:{
sendFather(){
this.$listeners.eventOne('123')
this.$emit('eventOne',123)
this.$emit("senddata",456)
            },
        },

    }

</script>

<style>
</style>

可以通过两种种方式实现给外层组件传参

第一种直接调用方法

第二种通过$emit方式

如果还需要继续深层次传递外层的方法 则需要继续传递v-on="$listeners",如果当前组件继续添加事件,则会合并外层一起传递给子组件,

这里个人觉得不是笼统传递不便于区分,建议以对象方式区分外层,父组件方法,就看官方后期了

  <son v-bind="$attrs" v-on="$listeners" v-on:eventThree="methodThree" ></son>

那么孙组件也可以相同方式给外层组件传参或者方法调用

就会收到合并后的一个事件监听器,则可采取同样模式进行传递给父,祖数据

总的来说

v-on="$listeners"将所有方法又绑定到组件相应标签 ,是绑定方法(.native除外)

v-bind="$attrs" 将所有非props属性绑定到相应标签 ,是绑定属性(.class和style除外)

vue3版本

移除了$listeners,合并到$attrs中,那么,属性和方法统一合并到$attrs