vue中组件之间相互传值的6种方法小结

 更新时间:2024年01月29日 08:22:15   作者:一花一world  
Vue.js 中组件间通信的方法有很多种,这篇文章主要为大家详细介绍了6种常见的直接或间接的组件传值方式,有需要的小伙伴可以参考一下

Vue.js 中组件间通信的方法有很多种,以下是6种常见的直接或间接的组件传值方式:

1. Props(父向子)

优点:

易于理解,符合单向数据流的原则,有利于代码维护。

缺点:

  • 数据只能从父组件传递到子组件,不能反向传递。如果需要多个层级传递,则需要逐层向下传递props。
  • 当应用规模扩大时,过度依赖props可能导致组件间耦合度提高。

2. 自定义事件(子向父)

优点:

实现了数据从子组件向父组件的传递,遵循响应式设计原则。

缺点:

  • 只能实现相邻组件之间的通信,对于多层级嵌套组件间的通信较为复杂。
  • 如果组件间交互复杂,可能会导致大量自定义事件的使用,影响代码可读性和可维护性。

3. $refs 和直接调用方法

优点:

在需要对子组件进行操作或获取其内部状态时非常方便。

缺点:

  • 违背了组件的封装原则,使父组件对子组件内部实现细节有过多了解和依赖。
  • 不适用于跨层级、非父子关系的组件间通信。

4. Vuex

优点:

  • 提供了一个中心化的状态管理机制,便于多个组件共享和管理状态。
  • 支持异步操作,适合大型项目,可以有效降低组件间的耦合度。

缺点:

  • 对小型项目来说,引入Vuex可能过于复杂,增加了项目的开发和学习成本。
  • 需要编写额外的store模块和actions/mutations/getters,增加了一定的代码量。

5. Event Bus(全局事件总线)

优点:

简化任意组件间的通信,尤其适合不具有直接关联关系的组件之间进行消息传递。

缺点:

  • 全局事件容易造成命名冲突,需要谨慎管理事件名称。
  • 当项目较大时,难以追踪事件的来源和去向,维护起来较困难。
  • 随着项目复杂度提升,过度依赖Event Bus会导致整体架构混乱,不易于调试和维护。

6. provide/inject

优点:

可以方便地在祖先组件中提供数据给任意后代组件,无需逐层传递props。

缺点:

  • 注入的数据不具备响应性(除非注入的是计算属性或者Vue实例的方法)。
  • 容易造成组件间隐式的强耦合,不利于组件独立性和可复用性。

详细代码示例

1. Props(父向子)

父组件向子组件传递数据:

父组件代码:

<template>
  <ChildComponent :parentValue="valueFromParent" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  data() {
    return {
      valueFromParent: '这是父组件的数据'
    };
  },
  components: {
    ChildComponent
  }
};
</script>

子组件代码:

<template>
  <div>{{ parentValue }}</div>
</template>

<script>
export default {
  props: {
    parentValue: String // 接收并展示来自父组件的值
  }
};
</script>

2. 自定义事件(子向父)

子组件向父组件传递数据:

子组件代码:

<template>
  <button @click="emitValue">点击传递数据</button>
</template>

<script>
export default {
  methods: {
    emitValue() {
      this.$emit('childEvent', '这是子组件传递的数据');
    }
  }
};
</script>

父组件代码:

<template>
  <ChildComponent @childEvent="handleChildEmit" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  methods: {
    handleChildEmit(value) {
      console.log('接收到子组件的数据:', value);
      // 更新父组件状态等操作
    }
  },
  components: {
    ChildComponent
  }
};
</script>

3. $refs 和直接调用方法

在某些情况下,可以通过 ref 获取到子组件实例并在父组件中直接调用其方法。

子组件代码:

<template>
  <div ref="childRef">...</div>
  <button @click="sendData">发送数据</button>
</template>

<script>
export default {
  methods: {
    sendData() {
      this.$emit('dataSent', this.someData);
    }
  }
};
</script>

父组件代码:

<template>
  <ChildComponent ref="child" @dataSent="handleData" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  methods: {
    handleData(data) {
      console.log('通过事件接收的数据:', data);
    },
    callChildMethod() {
      // 使用 $refs 访问子组件实例并调用方法
      this.$refs.child.sendData();
    }
  },
  components: {
    ChildComponent
  }
};
</script>

4. Vuex

使用全局状态管理工具 Vuex 来实现跨多个层级组件间的通信。

在 Vuex 中创建 store:

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    sharedData: null
  },
  mutations: {
    setSharedData(state, data) {
      state.sharedData = data;
    }
  },
  actions: {
    updateSharedData({ commit }, newData) {
      commit('setSharedData', newData);
    }
  },
  getters: {
    getSharedData(state) {
      return state.sharedData;
    }
  }
});

组件内使用:

// 任何组件内
<template>
  <button @click="updateData">更新共享数据</button>
  <AnotherComponent />
</template>

<script>
import { mapActions, mapGetters } from 'vuex';

export default {
  computed: {
    ...mapGetters(['getSharedData'])
  },
  methods: {
    ...mapActions(['updateSharedData']),
    updateData() {
      this.updateSharedData({ some: 'new data' });
    }
  }
};
</script>

5. Event Bus(全局事件总线)

创建一个全局事件总线来允许任意组件之间进行通信。

// eventBus.js
import Vue from 'vue';

export const EventBus = new Vue();

发送事件的组件:

<template>
  <button @click="sendMessage">发送消息</button>
</template>

<script>
import { EventBus } from './eventBus';

export default {
  methods: {
    sendMessage() {
      EventBus.$emit('customEvent', { message: 'Hello from component A!' });
    }
  }
};
</script>

接收事件的组件:

<script>
import { EventBus } from './eventBus';

export default {
  created() {
    EventBus.$on('customEvent', (data) => {
      console.log('Received message:', data.message);
    });
  },
  beforeDestroy() {
    // 不要忘记在组件销毁时解绑事件监听器以避免内存泄漏
    EventBus.$off('customEvent');
  }
};
</script>

6. provide/inject

Vue 提供了 provide 和 inject API 来实现祖先组件向后代组件提供依赖的方式(无需中间传递)。

祖先组件提供数据:

<script>
export default {
  provide() {
    return {
      ancestorData: this.someData
    };
  },
  data() {
    return {
      someData: '来自祖先的数据'
    };
  }
};
</script>

后代组件注入数据:

<script>
export default {
  inject: ['ancestorData'],
  mounted() {
    console.log('从祖先获取的数据:', this.ancestorData);
  }
};
</script>

以上每种方法都有其适用场景和优缺点,请根据实际项目需求选择合适的方式。

到此这篇关于vue中组件之间相互传值的6种方法小结的文章就介绍到这了,更多相关vue组件相互传值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue指令只能输入正数并且只能输入一个小数点的方法

    vue指令只能输入正数并且只能输入一个小数点的方法

    这篇文章主要介绍了vue指令只能输入正数并且只能输入一个小数点的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • vue导航栏部分的动态渲染实例

    vue导航栏部分的动态渲染实例

    今天小编就为大家分享一篇vue导航栏部分的动态渲染实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue.js body的css不生效问题及解决

    vue.js body的css不生效问题及解决

    这篇文章主要介绍了vue.js body的css不生效问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 使用vite构建vue3项目的实现步骤

    使用vite构建vue3项目的实现步骤

    通过本文,您可以了解如何使用Vue CLI创建Vue 3项目,配置Vite,利用其优势进行开发,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • 基于vue-cli 打包时抽离项目相关配置文件详解

    基于vue-cli 打包时抽离项目相关配置文件详解

    下面小编就为大家分享一篇基于vue-cli 打包时抽离项目相关配置文件详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Element Popover 弹出框的使用示例

    Element Popover 弹出框的使用示例

    这篇文章主要介绍了Element Popover 弹出框的使用示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • vue3.0使用vue-pdf-embed在线预览pdf 控制页码显示范围不生效问题解决

    vue3.0使用vue-pdf-embed在线预览pdf 控制页码显示范围不生效问题解决

    这篇文章主要介绍了vue3.0使用vue-pdf-embed在线预览pdf 控制页码显示范围不生效问题的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-01-01
  • Vue组件高级通讯之$children与$parent

    Vue组件高级通讯之$children与$parent

    这篇文章主要为大家介绍了Vue组件高级通讯之$children与$parent,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • vue3+ts实现树形组件(菜单组件)

    vue3+ts实现树形组件(菜单组件)

    本文主要介绍了vue3+ts实现树形组件(菜单组件),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • vue3中的ref,toRef,toRefs三个的作用使用小结

    vue3中的ref,toRef,toRefs三个的作用使用小结

    Vue3中ref、reactive、toRef、toRefs都是与响应式数据相关的,就此做一份笔记作为区别,本文重点给大家讲解vue3中的ref,toRef,toRefs三个是干嘛的,有什么作用,感兴趣的朋友跟随小编一起看看吧
    2022-11-11

最新评论