Why This Matters for Vue Props
Hey what's going on guys? Welcome to your 23rd vue.js tutorial and in this video I want to talk about the difference between primitive and reference types.
Okay, so although it's not a part of vue.js, I do want to talk about primitive and reference types because they are going to affect how you work with props in VJs. And if you don't know the difference between those two types, then you're going to think that vue.js is exhibiting some kind of weird behavior when it comes to using props. So what do I mean by primitive and reference types?
Understanding Reference Types
Well first of all, primitive types are strings, booleans, and numbers. Reference types are objects and arrays. Now if we were to pass through a reference type as a prop to another component, much like we're doing here, we're passing this ninjas property which is an array which is a reference type. If we were to pass a reference type like this to another component as a prop, then what we're doing is actually just passing a reference to that original data. We're not passing through a new set of data here which is stored in this component, we're just passing through a reference to that data.
Therefore if we were to edit that data in here once we've passed it through, that is going to edit indirectly this original data, not just the data locally in this component. It's going to edit it up here where it was originally created and stored once in memory.
How Primitive Types Differ
Okay, so how is that going to affect things? Well if you think about it, this data might be passed through to several different components, and if we were to edit this data in one of those components, then it's going to update this data where it's originally created. Therefore it's going to update in those other components because we're just passing references to this original data through to them as props, right?
So it's not the same if we work with primitive types. If we were to pass through a primitive type such as a string as a prop to this component, then if we edit it in here, then it's only going to edit that local version of that prop, that variable in this component. It's not going to be passed through a reference to the original one. It's going to create a new one in here and just edit that one. So if we were to define a string here, pass it through as a prop into several different components, then in one of those components edit that string, it's only going to update the string in that one component that we update in, and it's not going to affect this original data here. Okay, so I'm going to show you a couple of examples now of how they behave differently.
Demo: Mutating a Reference Type Prop
So say for example we want to edit the reference type, the array which we passed through here of ninjas. We want to delete a ninja and see how that affects everything else.
Well let's create a button to do that. And I'm going to add a click event, so v-on:click and this is going to equal a function called deleteNinja. And then inside, we'll have text saying 'Delete Ninja'. Okay, so now we need to hook this up to this event right here, or this function rather. So let's copy it and come down here and create a method. So methods, and this is an object, and inside we need this method which is a function. And inside this function, we just want to delete one from the ninjas right here.
Now when a prop is passed to us, I said that we have access to it much like we do when we define data here. So we can just say this.ninjas to access it, then we can say pop() to pop one of those elements out of the array from the array, so it's going to delete one essentially. So if I save that now, check this out in the browser. Just going to refresh, and if we click delete ninja, you're going to see one of those ninjas go. And again, goes, again, goes, again, etc. We're deleting ninjas.
How Reference Mutations Affect Multiple Components
So like I said, what we're doing here is just deleting ninjas from the original data source right here, okay, because it's just a reference type. So what then if we had two of these components and we're passing through that data to both of those components? Well let's just add another one in and a hr in between them so we can separate them and save this and view this in a browser. So now we have two lots of this, right? And if we delete a ninja in one of them, then it's deleting a ninja in the other. And same goes if I delete a ninja here, it's deleting a ninja in the other one too. And that's because we're deleting the original source of the data because it's a reference type. And the original source of the data is then being passed to to both of these instances of the component. So it's updating then in both. So that is how reference types work.
Demo: Passing a Primitive Type Prop
Okay, so let's get rid of this now and instead I want to show you how we work with primitive types, because this behavior is not the same for primitive types. It's the opposite.
So say for example now, in our header we have this title, right? Say now we want to define this in the root component and then we want to pass it down as a prop to the header, right? So let's do that. First of all, let's define the title down here. So after the ninjas, we want a title and this is a string, which is, remember, a primitive type. And let's call this 'Vue Ninjas', right? So there's the title. Now we're going to pass it down as a prop. So we know how to do that. We come up to the component tag and we say v-bind, then the prop name which is title, and we set that equal to the title which we've just defined down here. Okay, so we're passing that as a prop now to this component. So let's save it, go to the header, and receive that prop. So in our object we'll say props, and then we're going to receive the title as a prop, and that is going to be an object, and the type will be of String.
Passing a Primitive Prop to Multiple Components
Okay, so now we're receiving that prop in here and we're outputting it in the header. So let's save it just to make sure it's working. And yeah, we get 'Vue Ninjas'.
Now let's do the same for the footer, because we have 'Vue Ninjas' in two places, right? So let's pass the same data defined here, the same title, through into the footer. So I'm going to copy this and I'm going to add that as well to the footer. So we're just passing through this title prop to the footer as well, much like we did with the header. Save that and let's open the footer. And now instead of adding this here, what I'm going to do is say 'Copyright ' and then also tack on the title. But we also need to receive that prop. So again, props, this is an object, then we're receiving the title prop, and this title is of type String. Okay, so now we're receiving the same prop in the footer and we're outputting it here. So if we save this now, view it in a browser again, we can see we're still getting that down here. And if I refresh, it's still going to be the same. We're getting 'Vue Ninjas' in both the footer and the header. And I can demonstrate that it's going to both if I change this to just 'View', for example, then it's updating in both of these, right?
Demo: Mutating a Primitive Type Prop
So when we were talking about reference types, if I was to update a reference type piece of data or prop which is passed to us in a component here, it would also update here. However, these are not reference types, these are primitive types. So if I update this prop here, it's not going to update it here. It's going to exhibit a different behavior from the ninjas where they were reference types. So let's try it out.
So let's change this back to 'Vue Ninjas' to begin with. And then in the header, what we'll do is add a button to change the title, or rather, instead we'll just add a click event to this H1 so that when we click it, it changes the title. So we'll say v-on:click and that's equal to a function called changeTitle. And then let's define this function down here. So after the data, methods, and then this is an object, and then this method changeTitle is going to be a function which is going to change the title. And we can access the title by saying this.title and setting it equal to something else, right? So I'm going to change this to 'Vue Wizards'. So 'Vue Wizards'. So now if I click this, it's going to change the title, right? And it's only going to update in this one component: 'Vue Wizards'. It's not updated down here because these are not reference types. We're not editing the original data. Okay, we're just editing it right here. So my friends, that is the difference between primitive and reference types.