【vuejs】常用的组件之间数据通信方式总结

本文主要是介绍【vuejs】常用的组件之间数据通信方式总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

vue.js组件实例的作用域是相互独立的,不同组件之间的数据不能相互访问,组件有父级组件、子级组件、兄弟组件、如何选择组件之间的通信方式?今天就来总结一下常用的几种组件传值方式

1. 父子组件通信

1.1 Props

Props 是 Vue.js 中用于父子组件间数据传递的一种方式。父组件通过 props 向子组件传递数据,子组件通过声明 props 属性来接收这些数据。

  • 单向数据流:Props 确保了数据流的单向性,即数据只能从父组件流向子组件,这样做提高了组件间的解耦性。
  • 动态 Props:父组件可以使用 v-bind 动态地将数据对象传递给子组件,v-bind 可以是任何类型的数据,包括对象和数组。
  • 示例:
    <template><child-component v-bind:dynamic-prop="parentData"></child-component>
    </template>
    <script>
    export default {data() {return {parentData: {message: 'Hello from parent!'}};}
    };
    </script>
    

1.2 e m i t / emit/ emit/on

当需要从子组件向父组件发送数据时,可以使用 $emit 来触发事件,并通过 $on 方法在父组件中监听这些事件。

  • 自定义事件:子组件通过 this.$emit 触发一个事件,并可以附带数据,如 this.$emit('custom-event', eventData)
  • 监听事件:父组件使用 v-on@ 语法来监听子组件触发的事件,如 <child-component @custom-event="handleEvent">
  • 事件对象:在事件处理函数中,可以访问到事件对象,包含有关事件的信息,如时间戳和事件类型。
  • 示例:
    <template><child-component @trigger="handleTrigger"></child-component>
    </template>
    <script>
    export default {methods: {handleTrigger(data) {console.log('Event triggered with data:', data);}}
    };
    </script>
    

2. 事件总线通信

2.1 创建事件总线

事件总线(Event Bus)是一种在 Vue.js 应用程序中实现跨组件通信的方法。它通过创建一个新的 Vue 实例作为中央事件总线,使得不同的组件能够相互通信,无论它们是否在组件树中直接相关。

  • 实现方式:首先,创建一个事件总线的实例文件,例如 event-bus.js,并导出一个新的 Vue 实例。
    import Vue from 'vue';
    const EventBus = new Vue();
    export default EventBus;
    
  • 全局挂载:在主入口文件,如 main.js 中,将事件总线实例挂载到 Vue 的原型上,以便在任何组件中都能够访问。
    import Vue from 'vue';
    import App from './App.vue';
    import EventBus from './event-bus.js';Vue.prototype.$eventBus = EventBus;
    new Vue({render: h => h(App),
    }).$mount('#app');
    

2.2 事件触发与监听

使用事件总线进行通信时,组件可以触发(emit)事件和监听(on)事件。

  • 触发事件:任何组件都可以通过 this.$eventBus.$emit 方法触发事件,允许其他组件监听这些事件。
    this.$eventBus.$emit('custom-event', 'Some data');
    
  • 监听事件:组件可以通过 this.$eventBus.$on 方法监听事件,并定义一个回调函数来响应事件。
    this.$eventBus.$on('custom-event', (data) => {console.log('Event received:', data);
    });
    
  • 移除事件监听:如果需要,可以使用 $off 方法从事件总线移除监听器。
    this.$eventBus.$off('custom-event', listenerFunction);
    
  • 一次性监听:有时我们只想响应一次事件,这时可以使用 $once 方法,事件触发后监听器将自动被移除。
    this.$eventBus.$once('custom-event', (data) => {console.log('This will only trigger once:', data);
    });
    

事件总线提供了一种非常灵活的组件间通信方式,特别适合于非父子组件间的通信,或者当组件间的层级关系较远时。然而,使用事件总线时应谨慎,以避免组件间的过度耦合,确保代码的可维护性。

3. Vuex状态管理

3.1 State

Vuex 的 state 是一个用于存储应用级状态的对象,它包含了应用所需的所有数据。这些数据可以是任何类型,例如数组、对象或简单数据类型。

  • 集中管理:state 使得所有组件共享的数据集中管理成为可能,便于在不同组件之间共享和维护数据。
  • 响应式更新:Vuex 的状态是响应式的,当 state 中的数据发生变化时,所有依赖这些数据的组件都会自动更新。
  • 示例:
    const store = new Vuex.Store({state: {count: 0},getters: {doubleCount: state => state.count * 2}
    });
    

3.2 Getters

getters 是用于从 state 中派生出一些状态的方法,它们可以认为是 state 的计算属性。

  • 描述性名称:getters 通过描述性名称提供对 state 的读取,使得在组件中使用时更加清晰。
  • 组件内使用:在组件中可以通过 this.$store.getters 访问 getters,或者使用 mapGetters 辅助函数将 getters 映射到组件的计算属性。
  • 示例:
    computed: {...mapGetters(['doubleCount',])
    }
    

3.3 Mutations

mutations 是用于修改 state 的唯一方法。它们是同步的事务操作,当 state 需要变更时,必须通过 mutations 来完成。

  • 同步操作:mutations 必须是同步函数,这样 Vuex 才能追踪到状态的变化。
  • 变更状态:在组件中通过 this.$store.commit('mutationName') 触发 mutations,从而更新 state
  • 示例:
    store.commit('increment');
    

3.4 Actions

actions 类似于 mutations,不同之处在于它们可以包含异步操作。actions 通过 mutations 来间接修改 state

  • 异步操作:actions 可以执行异步操作,例如 API 请求,并在操作完成后提交 mutations
  • 组件内分发:在组件中通过 this.$store.dispatch('actionName') 分发 actions
  • 示例:
    store.dispatch('incrementAsync');
    

Vuex 状态管理提供了一种强大的方式来管理复杂的应用状态,通过集中式存储和严格的规则使得状态管理变得可预测和易于维护。

4. 属性与事件传递

4.1 $attrs

$attrs 是 Vue.js 提供的一个对象,包含了父作用域中不被 prop 所识别的特性绑定(class 和 style 除外)。当组件没有声明任何 prop 时,$attrs 会包含所有的父作用域绑定(class 和 style 除外),并且可以通过 v-bind 传递给子组件。

  • 透传属性:在多层嵌套的组件中,有时需要将某些属性传递给更深层次的子组件,这时可以使用 $attrs 来实现属性的透传。
  • 示例:
    <template><child-component v-bind="$attrs"></child-component>
    </template>
    
  • 配合 inheritAttrs:组件默认会将未声明的属性绑定到自身的根元素上,通过设置 inheritAttrs: false,可以阻止这一行为,然后通过 $attrs 手动传递给子组件。

4.2 $listeners

$listeners 是一个对象,包含了父作用域中的(不含 .native 修饰器的)v-on 事件监听器。它可以通过 v-on 传递给子组件。

  • 事件透传:类似于 $attrs$listeners 允许我们将事件监听器从一个组件传递到另一个组件,特别是当需要将事件监听器传递给深层子组件时。
  • 示例:
    <template><child-component v-on="$listeners"></child-component>
    </template>
    
  • 避免重复:使用 $listeners 可以避免在子组件中重复编写事件监听器,使得父组件能够统一管理事件监听。

通过 $attrs$listeners,Vue.js 提供了一种灵活的方式来传递属性和事件,使得组件间的通信更加简洁和高效。这些特性特别适用于组件库的开发者,他们可以构建出更加灵活和可复用的组件。

5. Provide/Inject API

5.1 Provide

provide 是 Vue.js 2.2.0 版本引入的一个 API,允许祖先组件向所有子孙组件提供数据。无论组件层次结构有多深,只要组件间存在祖先与后代的关系,provide 就能够起作用。

  • 数据提供:祖先组件通过 provide 函数定义可提供给后代的数据或方法。
  • 示例:
    provide() {return {theme: 'dark', // 提供一个 theme 数据toggleTheme: this.toggleTheme // 提供一个方法};
    }
    

5.2 Inject

provide 相对应,inject 允许子孙组件接收来自祖先组件提供的数据。

  • 数据注入:子孙组件通过 inject 选项接收祖先组件提供的数据。
  • 示例:
    inject: ['theme', 'toggleTheme'], // 接收 theme 数据和 toggleTheme 方法
    
  • 响应式:需要注意的是,provideinject 本身不是响应式的。如果需要响应式,可以借助 Vue.observable 对象。

通过 provideinject,Vue.js 实现了一种在组件树中跨级传递数据的方式,这在某些场景下比事件总线或 Vuex 更为便捷和高效。然而,过度使用 provideinject 可能会导致组件之间的耦合度增加,因此建议在确实需要时才使用此特性。

6. 直接访问实例

6.1 p a r e n t / parent/ parent/children

在 Vue.js 中,每个组件实例都有 $parent$children 属性,它们分别用于访问当前组件的父组件和所有子组件。

  • 访问父组件:通过 $parent 属性,子组件可以直接访问其父组件的实例,从而能够访问父组件的数据和方法。

  • 示例:

    // 子组件中访问父组件的数据
    console.log(this.$parent.someData);
    
  • 访问子组件:通过 $children 属性,父组件可以访问其所有子组件的实例数组。这允许父组件直接与子组件通信或调用子组件的方法。

  • 示例:

    // 父组件中调用第一个子组件的方法
    this.$children[0].someMethod();
    
  • 局限性:虽然 $parent$children 提供了一种直接的组件间通信方式,但它们也有一些局限性。例如,它们不支持响应式更新,且过度依赖这种直接访问可能会使组件之间的耦合度增加,从而影响组件的可维护性和可复用性。

  • 替代方案:在许多情况下,推荐使用 props、事件、事件总线、Vuex 或 Provide/Inject API 等更声明式的方法进行组件间通信,以保持组件的独立性和可维护性。直接访问实例的方法更适合于那些需要快速访问特定组件,且不会引起紧耦合的场景。

7. 插槽通信

7.1 插槽基础

插槽(Slots)是 Vue.js 中用于组件内容分发的机制,它允许开发者在组件的模板中预留一个或多个位置,这些位置可以被组件的使用者填充自定义的内容。

  • 内容分发:插槽允许将内容从父组件传递到子组件的特定位置,这为构建可复用组件提供了强大的灵活性。
  • 示例:
    <template><div><slot>默认内容</slot></div>
    </template>
    

7.2 具名插槽

当组件需要多个插槽时,可以使用具名插槽来为每个插槽提供不同的名称。

  • 具名插槽:通过 slot 属性为插槽命名,使得父组件可以指定内容应该插入到哪个插槽中。
  • 示例:
    <template><div><slot name="header">默认头部</slot><slot name="footer">默认底部</slot></div>
    </template>
    

7.3 作用域插槽

作用域插槽允许子组件将数据作为插槽的一部分传递回父组件,从而实现更动态的内容分发。

  • 作用域插槽:子组件通过 slot-scope 属性接收数据,并将数据作为插槽的一部分传递给父组件。
  • 示例:
    <template><ul><li v-for="item in items" :key="item.id"><slot :item="item">{{ item.defaultText }}</slot></li></ul>
    </template>
    

7.4 插槽的优缺点

插槽提供了一种强大的方式来构建具有高度可定制性的组件,但它们也有一些局限性。

  • 优点:插槽使得组件更加灵活和可复用,开发者可以根据需要插入自定义内容,包括布局和行为。
  • 缺点:过度使用插槽可能会使组件的模板变得复杂,难以理解和维护。此外,插槽不支持动态绑定,这限制了它们的使用场景。

插槽是 Vue.js 提供的一种声明式的内容分发 API,它为构建复杂的组件提供了强大的工具,但开发者应该根据具体场景谨慎使用。

这篇关于【vuejs】常用的组件之间数据通信方式总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027342

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/