背景: 在vue项目开发过程中,经常会遇见多层组件传递属性和方法的场景,当然解决方案有很多,在应对不同场景需求时,需要选择一个最合适的方案
对于组件之间传值的方式有很多,如
- props,适用于父子组件传值,也是最常用的方法;
- vuex,适用于任何场景,多层组件传值,父子、兄弟、无关联组件传值都可以使用,但是对于简单的父子组件等,用vuex显得有些臃肿;
- EventBus,多用于兄弟、父子组件传值,但使用在实际的项目操作中发现,如不能实现很好的事件监听与发布的管理,往往容易导致数据流的混乱,在多人协作的项目中,不利于项目的维护
- 当然还有父组件利用$refs调用子组件方法、子组件利用$parent获取父组件实例等方式
本文主要是提供一种利用$attrs、$listeners解决三层组件之间的传值的解决方案
现场景如下:A:父组件、B:子组件、C:孙子组件
直接上代码:
A:组件
<template>
<div class="app-container">
<B :name="name" :age="age" @handleName="handleName" @handleAge="handleAge" />
</div>
</template>
<script>
import B from './componemts/B.vue';
export default {
data() {
return {
name: 'Tom',
age: 20,
};
},
methods: {
handleName(form) {
console.log('this is form A name', from);
},
handleAge(from) {
console.log('this is form A age', from);
}
}
};
</script>
<style lang="scss" scoped>
</style>
B: 组件
<template>
<div class="app-container">
<!-- 通过 v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
<!-- v-on 绑定了$listeners 属性,C组件可以调用A组件传递的方法 -->
<C v-bind="$attrs" v-on="$listeners" />
</div>
</template>
<script>
import C from './componemts/C.vue';
export default {
props: {
name: String,
},
data() {
return {
};
},
mounted() {
console.log('name:: ', this.name); // Tom
this.$emit('handleName', 'B')// this is form A name B
}
};
</script>
组件C:
<template>
<div class="app-container">
</div>
</template>
<script>
export default {
data() {
return {
};
},
mounted() {
console.log('name:: ', this.$attrs.name); // undefined
console.log('age:: ', this.$attrs.age); // 20
this.$emit('handleAge', 'C'); // this is form A age C
}
};
</script>