DEV Community

Hands-on Vue.js for Beginners (Part 5)

Marina Mosti on February 22, 2019

This time around we're going to look (finally) at components! So get some ☕️ and let's get started. Here's the clean slate for today's article 😁 ...
Collapse
 
frfancha profile image
Fred

Hi Marina,
First a big thank you for this blog that I follow with great interest every week.
Could you elaborate a little bit on the change of prop in component?
Because the anti-pattern link that you give explains why it is a bad idea (and actually now forbidden) to change the value of the property itself in the component, it doesn't really speak about changing attributes of the property.
Which is what we would have done here by doing gameData.rating++ instead of game.rating++. We wouldn't have changed the property completely by doing gameData = {...}
?

Collapse
 
marinamosti profile image
Marina Mosti

Hey Fred, thanks for reading :)

When you change the attributes in an object or array based prop it will still trigger a re-render on the parent, the change is also untracked and will not emit an event because it's not being listened for.

Any changes to props directly are affecting two components, parent and child at the same time so the pattern of data delegation and communication is effectively broken. The parent will re-render and trigger overwrites of the data. In some cases it will "seem" like this is not a problem, but in parent/child relationships where a lot of data is being transferred or when the parent has a lot of re-rendering happening because of state changes you are going to get yourself a free headache and very little ways to debug it.

This is actually a GREAT question, but TLDR mutating props is a huge no no - data should only be flowing one way :)

Collapse
 
frfancha profile image
Fred

"mutating props is a huge no no"
Thanks for this.
We have a huge home made AngularJS application.
One of the base component of that is a "FieldEditor" directive.
Getting 2 props: dataRow and fieldName.
The fieldEditor component allows the user to edit the corresponding field of the dataRow.
E.g. in the parent having the row "Customer" with attributes "FirsName", "LastName", "Age", you would find3 FieldEditor in the html, 1 getting Customer + the string "FirstName" to edit the first name, another one for last name and a third one for age. Note this is an overly simplified version.
I was hoping to use Vue.js as replacement for AngularJS ... Apparently not a good idea?

Thread Thread
 
marinamosti profile image
Marina Mosti

I dont think this issue is related to the framework, but more on how you structure our components. The parent should "feed" data to the child, and the child should "tell" the parent when that data is modified through some sort of event or shared state.

Thread Thread
 
frfancha profile image
Fred

Hi Marina,
Hoping you will have the time to give yet another answer...
Sorry for coming again on this topic but this is quite important for us.
Here a mini-mini codepen showing what I mean:
codepen.io/frfancha/pen/gErWKG
In this pen you can edit the name (Joe) or the age (23) in any of the "field" component in the other one is updated, so "modifying" the prop properties (not the prop reference itself) seems working perfectly in Vue.js
So we can can still use our basic building block "field" component of our big application.
(PS our "field" component does much more than the code of the pen, e.g. when the field to edit is numeric it automatically provides a calculator and other such features)

Thread Thread
 
marinamosti profile image
Marina Mosti

Hello Fred, the fact that it "works" doesn't mean that it is correct. You will run into issues eventually when the parent starts re-rendering. The correct way to handle input wrapper components is by using a value prop and $emit with an input event so you can v-model on the parent.

vuejs.org/v2/guide/components-cust...

Collapse
 
glennmen profile image
Glenn Carremans

Hey I am loving this series so far! I have always wanted to get in Vue and have learned so much already with these weekly tutorial ❤️

Btw in the last code block I think there is a mistake:
game: {...this.gameData}
shouldn't it be game: {...this.game-data}, ?
Or did I miss some part 🤔 I think the error happened because at some point you switched from gameData to game-data .

Collapse
 
marinamosti profile image
Marina Mosti

Hi Glenn! Thanks so much for your comment :)

You are absolutely right! Somehow when I copied over the whole result I forgot to update that on the examples above. Nice catch! Also, thanks for letting me know :)

Collapse
 
dragz profile image
Roy Dragseth

Hi Marina. I can only join the praise you get for this tutorial. It is one of the best I've read in a long time. Thanks!

Two comments on the code example in this section:

I was slightly confused until I discovered the implicit conversion from camelcase to kebabcase and thus did not understand that 'gameData' in the component declaration corresponds to :game-data in the game-card tag.

Also, the game variable name is used in different contexts. Initially I thought it had to be the same in both the v-for loop and the component declaration, but after toying with the source code it became clear that game in data() is unrelated to the game looping index in v-for. (Pretty obvious in hindsight)

Both these things might be part of the folk-wisdom, but for a newbie like me it threw me off the track for 15 minutes.

Again, thanks for a great tutorial!

Collapse
 
marinamosti profile image
Marina Mosti

Roy, thanks for your kind words :) Nice catch! It's sometimes hard to look at all the angles where someone can trip on, but your input is super valuable. Hopefully, it also helps more people that got tripped up by the same thing

Collapse
 
ericstolzervim profile image
Eric Stolzervim

Thanks for this lesson.

When you increase the rating, it increases the copy (not the rating in games). So when I open another browser, I don't see the rating changes that the first browser made.

How do I change the rating in games?

Collapse
 
marinamosti profile image
Marina Mosti

Hey Eric! Well, the status of your component is not going to persist through browsers unless you're storing it somehow on a server and then authenticating a user, this is way beyond the scope of these tutorials.

In order to change the parent's data you need to communicate to the parent of the component that the child's data has changed. You can accomplish this with either events or vuex (or some sort of state management).

I will eventually get to this in the tutorials, but if you want to try to skip ahead take a look at the docs and read about $emit and how to fire an event from your child component. You will also need to use a watched property as well, so this is kind of advanced in regard to what we have covered

Collapse
 
jyotik09 profile image
jyotik09 • Edited

Hi Marina,

Kudos to you for this super simple and insightful blog...
I came across this when i was searching for something in Vue.js and this really intrigued my quest to learn more about Vue !! :)

Collapse
 
marinamosti profile image
Marina Mosti

Hey Jyotik09, thanks for your comment :) I'm really glad you liked it! Vue is a really fun framework to work with

Collapse
 
pravinkumar95 profile image
Pravin kumar

Nice tutorial. Got a little bit confused with game-data and gameData. Eventually got used to it. Great Work!

Collapse
 
rodz profile image
Rodrigo Gomez

Interesting how Vue keeps the reactivity intact but with added costs and concepts with components. The semantics changed from data: {} to data(){return copy{}}.