VueJS connects unrelated (as in parent / child) components

I am studying vue.js and asking a question about how to solve a specific problem.

My root component has the following pattern:

<div class="container"> <div class="stage"> <map :current-time="currentTime" :recording="recording"></map> <player :track="track" :current-time="currentTime"></player> </div> <control-panel :current-time="currentTime"></control-panel> </div> 

In principle, the <player> component has a <video> element inside which the specified track will be loaded (hidden hidden controls). Thus, in fact, it will control the state of the application as the video plays (current time, playback state, etc.). However, <control-panel> has a panel for cleaning and buttons that determine the status of the video (play / pause, search). Obviously, a change in this general state in one of the components will affect the other two components (the map will also develop in accordance with the current time).

However, I wonder if this will be more appropriate and whether Vue supports component references so that I can provide a <control-panel> link to <player> so that it can accept state changes directly from it.

Or should it be done in some way by transmitting on the basis of the "global state" or "event-broadcast"? Before I fix it, consider an example where there are two <player> and two <control-panel> that are not hierarchically connected, but one panel A works with playerA and panel B with playerB. In this case, I think the broadcast option falls off the table, right?

Any suggestions are welcome, especially since I'm just learning Vue.

Update 1

So, after meeting Vue and listening from the community, I think I came up with a smart solution to sync <player> and <control-panel> together. My markup changes to the following:

 <div class="container"> <div class="stage"> <map :current-time="currentTime" :recording="recording"></map> <player :track="track" :current-time="currentTime" v-ref:player></player> </div> <control-panel :current-time="currentTime" v-ref:player-controls :player="$refs.player"></control-panel> </div> 

Note the addition of the v-ref attributes to <player> and <control-panel> , as well as to the attribute :player="$refs.player" . This allows me to logically connect with each other with each other. It makes sense in my head for a control panel to know who or what is controlling. I am going to check this further, but at the moment it seems to work.

As for the <map> binding, I end up using a broadcast or just a two-way currentTime updated <control-panel> . I will update this post when I go and either mark the correct answer or post my own if it differs from any of the answers.

Update 2

Read my answer below. I was able to successfully solve the problem using the approach below.

+5
source share
2 answers

The solution included the approach described in Update 1 . Since the <video> element has a well-designed API, translating it into a reactive component was quite simple (though tedious).

The wrapper for the video element ended with the creation of several computed attributes as follows:

 'currentTime': { cache: false, get: function () { return this.$els.player.currentTime; }, set: function (value) { this.$els.player.currentTime = value; } } 

The cache: false property should be used because the attribute is not attached to the reactive element and must be recounted every time the attribute was requested.

Not to make the component completely reactive was intentional. That is, I could define the necessary attributes as props with the assumption that they can be provided and synchronized with the parent. These attributes will be internally updated whenever the <video> element fires a state change event.

I also ended up distributing the events of the <video> element outside the component's parent using the $emit method. This was done because the components simply introduced HLS and acted as a state driver. Thus, it was acceptable that it was not completely reactive and imitated a simple <video> element.

The control panel successfully references the player component specified in Update 1 . Having received the pen on the player, it was easy to subscribe to its events using $on , and then simply hit its calculated properties on a state change event.

Finally, the map was a little easier to implement, since it corresponded to the more or less simple stream described in all other Vue examples. In fact, the parent of the card was tracking the current time. This variable was actually updated using the control panel with the attribute :currentTime.sync="currentTime" . However, to the map, she felt the same as if the parent himself had updated the time.

0
source

I think it is a good idea to leave them as independent components;

you can then disable the control panel component, if you want, using another that uses the same interface

(similar to disabling Stripe with another payment processor in an e-commerce application)

$broadcasting and $dispatching work well even with several players present, if you go through the identifier key with each transmission / send, so that each component receiving the message can immediately determine whether it was sent for them.

0
source

Source: https://habr.com/ru/post/1236477/


All Articles