未加星标

Understanding Components Communication in Vue 2.0

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二04 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

The way components communicate, in Vue, is through props and custom events. And with Vue 2.0 release, this system has changed quite a bit ― it has actually gotten simpler!

But still, this transition might not feel so obvious to many developers. So, in this article, I’d like to show you the different cases in which components communicate, and how to handle each one properly.

Three cases of components communication

Let’s start first by defining the three cases that components communicate with one another:

From a parent component to its direct children. And this happens by passing data to the child via props ! Nothing more, nothing less! From a child to its direct parent. Globally, between different components. This includes child components with their ancestors (non-direct parents). Or parent to its non-direct children. Or between sibling components.

I’ve already explained how the first case works. So, let’s get into the other two cases.

Parent-Child communication

It’s called parent-child communication because they are directly related to each other ― note that we’re talking here about the second case, which is from child to its direct parent.

To accomplish this kind of communication, you have to do two things:

First, Fire an event from the child component using $emit(eventName, [data]) . Listen to it on the parent using the v-on:event-name directly in the template where the child component is used.

Here’s a quick example:

Let’s say you’ve built your own custom dropdown component that contains a bunch of options which you pass from the parent. When an option is selected in that dropdown, it should emit an event to its parent, so it can do its stuff.

Here’s what happens when an option is selected in Dropdown.vue :

methods: { selected () { // assume 'this.selectedOption' is defined in the data object this.$emit('option-select', this.selectedOption) } }

Now in the parent component ― let’s call it NavBar.vue ― we’ll have something like this (note that I’m using the shorthand for v-on which is @ ):

<template> <div class="nav-bar"> <!-- other elements --> <dropdown :options="someOptions" @option-select="onOptionSelect" ></dropdown> </div> </template> <script> export default { methods: { onOptionSelect (option) { // handle it here } } } </script> Listening to native events

To make it easy to differentiate between listening to custom events and native events ( click , keyUp , etc), Vue 2.0 lets us specify that using the .native modifier. Here’s an example:

<my-component @click.native="onComponentClick"></my-component>

This means, when <my-component> is clicked, we’ll treat it as any other normal event on any element (such as <button> ).

This also means, you can define your own custom click event on that component without any conflicts ― maybe you want that event to be emitted when the user clicks on a particular part in that component ― not the whole component.

In this case you don’t have to use that modifier:

<!― listening to click event which was emitted from my-component ―> <my-component @click="onComponentClick"></my-component> Non Parent-Child communication

In other words, global component communication. In Vue 1.0, we were handling these kind of events using the two instance methods:

$dispatch : to fire an event that propagates upward along the parent chain. $broadcast : to broadcast an event that propagates downward to all descendants (all children).

Now in Vue 2.0, those methods are deprecated; there are several reasons for that:

As the component’s tree structure gets larger, it becomes very hard to maintain and reason about. For each modification you do, you have to check if those events are still passed to their handlers correctly ― which sometimes requires some workarounds until everything is back to normal. This means, in other words, events are tightly coupled with the component’s tree, which is always bad! Attaching multiple listeners isn’t that intuitive, because the normal behavior is to stop propagation on the first handler, unless you return true from it. There’s no explicit way to pass events to sibling components ― a workaround we were using is this: this.$root.broadcast('event-name') , which doesn’t feel good, does it?

So, what’s the solution instead? Well, the solution is get rid of those methods altogether, and handle all the communications through what we call the event hub (or some call it event bus ).

In its simplest definition, it’s an empty Vue instance that you use globally to fire and listen for events anywhere you want in the component’s tree.

So, obviously, like any other vue instance, we have these methods available for that:

eventHub.$emit(eventName) to emit an event. eventHub.$on(eventName) to listen for an event. eventHub.$off(eventName) to remove event listeners.

As I just mentioned, this eventHub is an empty Vue instance which you’d create like this: const eventHub = new Vue() .

This needs to be globally accessible

For everything to work correctly, you need to make sure that this eventHub is accessible globally. And this depends on how your application is structured.

If you’re building a simple non-modular app, you can attach that instance to the browser’s window object.

However, for module-based applications that use bundling tools like Webpack or Browserify , you can do that by exporting that instance from a certain file and then import it wherever you need it.

// src/shared/EventHub.js export default new Vue()

Now in other components, you would import it like this:

import eventHub from 'src/shared/EventHub' Example

Let’s say, you have this component’s tree:

component-one => component-a, component-b component-two => component-c, component-d

In this example, we have two main components named component-one and component-two where each one contains other nested components, as described above.

Let’s imagine that we want to pass an event from component-b to component-c .

To do that, we first need to emit that event from component-b :

import eventHub from 'src/shared/EventHub' // … methods: { doSomething () { eventHub.$emit('component-b-did-something', someData) } }

Now, in component-c , you would listen to it like this:

import eventHub from 'src/shared/EventHub' // … mounted () { eventHub.$on('component-b-did-something', (someData) => { // handle it however you want. }) }

As simple as that! The great thing about this approach is that you’re no longer concerned about the components tree structure. In other words, events can be emitted from any component and handled by any other component regardless of their relationship.

One last note

Although it seems that this is the ultimate solution for any complex components communication, it is not! Because imagine how unmaintainable this can become as your app grows more in complexity.

Luckily, for those cases we have a dedicated solution for that, which is Vuex . If you’re building any complex SPA and you’re not using Vuex yet, I highly encourage you to take the time to learn about it as it’ll make your life much easier in those case.

In conclusion

To finish up this post, let’s review the different cases of components communication:

From parent to direct children, no custom events required; just use props . From children to their direct parent, use $emit(eventName) in children and the directive v-on:event-name in the parent. Globally (from any component to any component), use the global event bus . Or use Vuex for more complex cases.

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

分页:12
转载请注明
本文标题:Understanding Components Communication in Vue 2.0
本站链接:http://www.codesec.net/view/484041.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(40)