Vue2中的$listeners
用于底层组件向高级层组件传递信息。
例如有 父组件A,子组件B,孙组件C 三个组件,如果C传递信息给B则可直接使用$emit,如果是C向A传递信息还使用$emit,则就需要C先$emit给B,B再$emit给A,这种方式比较繁琐,则此时可以使用v-on="$listeners"来满足当前需求。
用例:
C组件
<template>
<div @click="onClick">C组件</div>
</template>
onClick(){
this.$emit("Msg",'123')
}
B组件
<template>
<cCom v-on="$listeners"/>
</template>
A组件
<template>
<bCom @Msg='Msg'/>
</template>
methods:{
Msg(val){
console.log(val) //123
}
}
Vue3中的$attrs
如下 父组件App,子组件parent,孙组件children 三个组件
App.vue:
<template>
<parent to-parent="给父元素的数据" to-children="给子元素的数据" @clickEvent="clickEventCallback" />
</template>
<script setup>
import parent from 'parent.vue';
const clickEventCallback = () => {
console.log('在App.vue接收到点击的回调了');
};
</script>
parent.vue:
<template>
<div>
这里是parent:
<p>{{ props.toParent }}</p>
<children v-bind="$attrs" />
</div>
</template>
<script>
export default {
inheritAttrs: false,
};
</script>
<script setup>
import children from "./children.vue";
const props = defineProps({
toParent: String,
});
</script>
children.vue
<template>
<div @click="onClickFn">
这里是children:
<p>{{ props.toChildren }}</p>
</div>
</template>
<script setup>
const props = defineProps({
toParent: String,
toChildren: String,
});
const emit = defineEmits(["clickEvent"]);
const onClickFn = () => {
emit("clickEvent");
};
</script>
结果如下图所示:
如果在parent.vue里也在defineProps接收toChildren,那么被parent.vue截胡的children.vue里就取不到参数了。【因为$attrs传递的就是上级props不接收的参数】
同理,children.vue里的defineProps追加toParent参数也是取不到的。
当然,如果parent.vue里也想要children.vue的toChildren参数,也可以神不知鬼不觉的顺手牵羊: parent.vue:
<template>
...
<p>{{ attrs['to-children'] }}</p>
</template>
<script setup>
...
import { useAttrs } from 'vue';
const attrs = useAttrs();
</script>
结果如下图所示: