Vue Router Live Workshop
Laurie Barth: [00:00] Hi, everyone. I'm Laurie. Nice to meet all of you. We are here to talk about Vue Router. Did everyone successfully pull down the Git repository that was sent to you? Yes?
Chris: [00:15] Yeah.
William: [00:16] Yeah.
Laurie: [00:16] Good. Everyone has jumped over to the start here branch instead of the master branch?
Chris: [00:26] Yeah.
Laurie: [00:26] If you haven't, do that now because if you're on the master branch, all of the stuff we're about to do is done for you, which is cheating.
Chris: [00:32] [laughs]
Laurie: [00:34] No cheating in my workshops. All right. I am going to share my screen. Can everyone see that? We should have a VS Code and a browser with nothing in it.
William: [00:54] Yeah, I can see it.
Laurie: [00:55] All right. Where did my chat go? That's annoying. There we go, OK. We are going to start from the very beginning. This is running, just because I wanted you all to be able to see it.
[01:12] However, you access your project directory, whether that's inside of VS code or on a separate terminal, that's what we're going to do. For most of this workshop we're going to do what I'm referring to as "call and response."
[01:24] I'm going to do something and show you how to do it, and then I'm going to give you a little bit of time to do it on your own. We can trouble-shoot if people have issues. Sound good?
William: [01:33] Yeah.
Laurie: [01:34] We're starting from the very beginning, which means in order to have an entire workshop about Vue router, we actually need to be able to use Vue router. I am going to install it. I use NPM. If people use Yarm, that's fine.
[01:50] NPM install, save, and it's called Vue router. That'll take just a second. Depending on your Internet speed it'll take a little bit longer. If you want to do that while I'm talking through these first few steps, that's OK. Just have it running in the background.
[02:09] If we go over to our package.JSON we see that we now have Vue router. We no longer have to worry about setup for the rest of this workshop. Isn't life grand? OK, so in order to use Vue router we actually need to import it. We're going to do that.
[02:31] Now we have to set it up. There are few different things we want to do. We want our Vue application to use Vue router. We want to define some routes, which are going to be empty for now. That's the majority of what we're going to focus on today.
[02:53] Then we want to make a router that's using what we've defined that's going to take our routes. We're going to be in mode history. There are a couple of different modes in Vue router that are possible. History is just the prettiest and the cleanest, which makes it easy for us to do what we're doing today.
[03:20] There's also hash mode and a couple other things. This is actually not the default. It just is going to make it cleaner for workshop purposes. We want to pass our router in to our application. That is our entire setup step.
[03:37] What I want you to do is however you want to import Vue router, this is just a naming assignment. I've called it Vue router, but you could call it whatever you want. Make sure that you're using it. Defined a empty array as your routes.
[03:52] Create a router that's using your routes. I would recommend mode history just so you can follow along the same way. Then pass that router into our application. I'll give you a few minutes to do that. If you run across any issues, let me know. I'm going to confirm for all of us that we didn't break anything.
William: [04:18] What was the install command, the one you ran again for router?
Laurie: [04:22] I ran and NPM install --save Vue router. It's --save, but I've always said minus minus. No idea why. Weird quirks that no one ever calls you on as long as it works.
Chris: [04:42] It's that math background, I think.
Laurie: [04:43] It probably is.
Chris: [04:47] Does the order you pass in router in the view instance or the new view instance matter on line 15?
Laurie: [04:58] Here?
Chris: [04:59] Yeah.
Laurie: [05:00] Yeah. It should come first. It's an edge case. For most instances, you're not going to have problems with it, but best practices is that it comes first. There's other stuff you can pass in here, too. Don't save Vue 3, because technically, routing didn't change between Vue 2 and Vue. Other things changed, but routing didn't.
[05:22] Vue router is separately versioned. It works with view 3, but it's not actually a view 3 change. This is the same for view 2 and 3, until they tell me it's not the best.
[05:35] I talked to a core team member last week and it's not the case yet. Had to be sure.
Chris: [05:40] A whole week of uncertainty?
Laurie: [05:43] A whole week of uncertainty, exactly. Does everyone have that?
William: [05:52] Not yet.
Laurie: [05:57] Good here. There is one more thing that we're going to want to do. I'll do this while we are finishing the other piece. Inside our app.view, this is actually already here, because I did it for you, router view. This is just defining a connection to our router.
[06:21] This is where the pages we route to going to show up. If we added a header and footer, they would always be surrounded with our router view in the middle. This is part of our basic setup. It doesn't technically exist to start, but I cheated and I gave it to you. I don't remember why I did that, but it's here. Yay. Things for free.
[06:43] [background sounds only]
Laurie: [06:57] How are we doing?
Chris: [07:01] Doing good on my end.
Laurie: [07:03] What's happening?
William: [07:05] It says that the routers are clear, but this value is never read...
[07:10] [crosstalk]
Laurie: [07:13] Did you take router and pass it into this new Vue statement? Do you have this line?
William: [07:21] No, I just saw that. Let me add that.
Laurie: [07:23] Cool. That's fine. This is why we do call and response, so you can ask questions. You don't have to do this all on your own. Good?
William: [07:33] Yep. This is working.
Laurie: [07:35] We've done the setup. Now we get to define routes. What's really wonderful about Vue router and why I think it is superior to the routers in most other frameworks is that any set of routes that you have are an array, and each object in them is a route record. Each object is its own route.
[07:58] You can add all kinds of stuff to it, but each one is self-contained. We are going to make the most baseline route that we can to start. To do that, we want to import the component that we're going to use. You can follow exactly what I'm doing here.
[08:20] We're just going to import home. I've defined a bunch of components that we can use, so we don't have to make them for ourselves. Inside of here, we make an object, which is our route record. There are two things that are required. The first is path. In this case, we're just going to make it the /, so it will be our home.
[08:44] The second is component. That's what component we're sending to based on the path we've defined. That is it. That is the only thing that is required to make a route. Just one thing to note is that if we wanted to, we could import this directly here with an at statement and some other stuff. Personal preference is I like the separation of concerns of having all of our imports up top.
[09:14] Know that if you want to do that you can, but we're going to do it this way. As soon as I save, you'll see that we are on the home page. Take a second and get yourself a home page.
Chris: [09:36] Going back to when you're explaining the app.view, does the router view become the entry point into your application when you define it?
Laurie: [09:47] It does. I don't want to say entry point, because you can have more than one, which we will see later. It is just defining a specific window in which your component appears based on the routing information given to it.
[10:03] That allows for you to theoretically have multiple in parallel that are appearing in different places in your application, which we'll get to way at the end.
[10:17] If you think of it, if you're familiar with a Gatsby, React, or Angular, there are similar concepts where you do layouts and then everything that's inside the layout. It's that kind of a concept.
[10:30] Everything that you put on the outside and then your router Vue is the inside and whatever your defining and navigating to will render inside of there. It's basically a placeholder for what's going to show up based on the routes you send it to.
Chris: [10:46] That makes sense.
Laurie: [10:49] Everyone have a home page?
William: [10:53] Waiting for mine to come up.
Laurie: [10:55] Waiting for it to come up.
[11:03] The next thing we are going to do is we're going to import a couple other pages. This is going to get a little repetitive. I do apologize for that. I wanted us to have multiple components so that we can start seeing some of the different pages. Makes it a little bit easier.
[11:24] I'm importing blog and Egghead. As you can tell, we have a nice theme going on here. You'll see throughout that we'll import all of these eventually. We're going to make another object. In this case, we're going to set a path that isn't a / because / can only be one place. We're going to make it Egghead. Our component is going to be Egghead.
[12:02] Then we're going to do the same thing. We're going to make another route record. Its path is going to be Egghead, but its component is going to be blog because I want you all to see what happens when we do that.
[12:16] If we navigate to Egghead...This is why we do history mode, by the way, because in hash mode we'd have to do something like that, which is just ugly and not as pretty for the purposes of a workshop.
[12:28] This is where Egghead videos go. That's what the Egghead component says. The very first path to match gets priority. It's not a fall-through. It won't keep going and override and override and override and then the last one gets priority. It's the first one it hits. It won't look for any more. That make sense?
William: [12:56] Mm-hmm.
Laurie: [12:58] Just for now, we'll make this path blog. Then all of a sudden, we can see we can get to blog too. Make both of these because we're going to mess around with them and add more stuff to them.
[13:16] I find the prioritization really important because when we do wildcard paths later, we will see in which circumstances it matters what order they're in. Sometimes, it does. Sometimes, it doesn't. Depends on what you're doing.
[13:35] It will always be the first one that matches. That gets really important when we talk about sub-routes and other things where you could be hitting multiple. The first one always wins. How we doing? Everyone got these? Was everyone able to navigate to them and make sure they both work?
William: [14:01] Yeah, it's the same.
Laurie: [14:14] Oh, Chris got here. Hi, Chris.
Chris: [14:19] Hello.
Laurie: [14:19] What did you miss?
Chris: [14:22] I came in when you were starting to do the first path.
Laurie: [14:25] Good. You're fine. If you want to cheat, you can look at the master branch. You just need to be able to wire this up.
Chris: [14:35] Dope.
Laurie: [14:38] How we doing, William?
William: [14:42] Just finishing up with adding the second path.
Laurie: [14:47] Perfect. The next few lessons are what I call or lessons. I'm going to introduce a topic. I'm going to show you three or four different ways of doing it. I'm going to land on one. I'm not asking you to do it all three ways.
[15:08] When you're doing your call and response, pick whichever way you prefer. I just want you to see all the different ways you can access this information and send this information through your routing and navigation.
[15:20] Options are important because there are circumstances in which you will want to do one versus the other. You should be aware of them, but we don't need to add all of them at once because they are redundant.
[15:32] We are going to pass parameters in our route. You may be familiar with the fact that people like to access an ID of a blog, for example. They're just not going to a blog page. They want to be able to access other information.
[15:49] The first way we're going to do that is we're going to add a / and a colon and ID. ID is now the name of the parameter we're looking at. If we're thinking of a object, this is our key. Then the value will be whatever we pass through here.
[16:06] Now, if we go to blog view, we will see this is blog number ID. We actually want to do something here. We don't just want to have a fake ID. In Vue, the way we access this is we have double curly braces. It's this.$route.params. Then we're using the key that we want, which in this case is ID.
[16:34] If we save this, you'll notice that this no longer works. We can no longer see anything on this page because blog no longer matches a path. Blog/1234 matches a path, or blog/anything matches a path. There has to now be a / and something else that comes after blog. It doesn't match otherwise. Vue is very specific. It's looking for a direct match. This is one way to access it.
[17:13] Another way to access it is to assume that we might want to mess with it. Let's say we want to retrieve our blog based on this number or anything else. It would be nice to be able to do this directly in our JavaScript instead of just display the information.
[17:29] I'm not going to get into the nitty-gritty details, but we want a computed function. We're going to call it ID. We are going to return exactly what we had up here. We're going to return this.$route.params.id. Now we're accessing it as if it were a property, but it's really a function.
[17:59] The same thing happens. It works identical. The only difference is that we can mess around with things in the JavaScript if we wanted. If we wanted to add a number, for example, we could do that. Obviously, it's cast to a string. You could turn it to a number and then add a number. There's things you can do here that you couldn't do just by direct access in our template. It's nice to know we can do both.
[18:26] Now, the last thing we can do is to decouple our ID property away from routing. It may be that you want to be able to use this component and not always route directly to it, in which case it would be very useful to pass ID as a prop instead of passing it directly through routing.
[18:54] We can do that, but it requires going back to our route record and setting props to true. That's all it is, a key value pair props to true. Then we go into our log file. I'm going to remove all this computed stuff. I'm going to do props. It's accessing ID.
[19:29] Again, we're accessing it the same way with our curly braces. In this case, we can now use this component. Whether or not it's coming through routing, it can come through props. What it's doing is it's assigning all of our route parameters to an object that come through our component props.
[19:52] This is not the only thing we can do with this props key. We could also pass an object. We could also pass a function. The Boolean is the most straightforward way of doing this, but I want you to be aware that if you want to go more in-depth and do more complicated things with passing information in your parameters through props, you can do so. We are not going to cover the extensive examples here.
[20:18] Based on any of those options, either accessing it directly in your template, accessing it through a computed method in your JavaScript, or accessing it through props, I would like us to add an ID to our path. Let me know which one you chose because I'm kind of curious.
[20:39] [background sounds only]
William: [21:10] Could you go back to the main JS page?
Laurie: [21:12] Sure.
Zach: [21:22] How would you define path in multiple props?
Laurie: [21:29] If you pass in multiple params, you'll have another key. Who asked that question? Was it Zach?
Zach: [21:39] Yeah, it was Zach.
[21:41] [laughter]
Laurie: [21:41] There you go. See you could do something like that and then again it won't match. We could go over here and we would say ID, and then we could say Zach. Then we can show Zach. The test is not showing up. I probably spelled something wrong along the way. This is why you don't add random things in the moment. [laughs] You haven't tested.
[22:10] That should work, or something very similar.
Zach: [22:14] You have to miss the route like that? Could you add a query parameter?
Laurie: [22:22] Yeah, you can add a query parameter. You can do...Accessing query parameters is actually a little bit different than accessing a route directly. Instead of this dot route dot params, it's this dot route, if I'm not mistaken, dot query params. They are accessed differently, but it's a very similar concept. Asking me keywords on the fly, rude.
Zach: [23:00] Sorry.
[23:00] [laughter]
Laurie: [23:01] What was the syntax on the function use? The syntax on the function is that you make computed your key which is an object. Then you define whatever methods you have that are computed methods. The keyword that you're accessing is the name of the function itself.
William: [23:32] All of the same tag we were passing into the h1 on the blog component.
Laurie: [23:38] It's this dot route dot, oops if I can spell. Dot route, dot params, dot ID. None of this is going to work because I've made a mistake. [laughs] I'm showing three different ways at once. I will decide on one and that'll be the way that we have it so we don't break the rest of the project.
Zach: [24:03] How you decide, is that how dynamic you want your view to be?
Laurie: [24:11] It depends what you want to do with the params. If you just want to display something, then you'd go this route. If you want to do anything else, this is not the right way to go. Most of the time, you're going to want to access it directly in your JavaScript and do some kind of computing with it.
[24:30] The prop situation is where you anticipate something being both a top-level routing component and a component that might be nested in some other view where you'd want to pass that information.
[24:43] My inclination is that that is rarer than one might think, that you would want something that acts as a full page and acts as an embedded component. The situation where you can see it happening is because you can have multiple parallel routers.
[25:00] If it's already a nested component on a page, then you can add it. I like doing the function way more than setting props. I agree. I like the function way. The props is really only in case you ever need to access this component without routing directly to it because you can't.
[25:21] It'll break if there are no props to access. That's if you want to have it as a nested component in another view. Yes, I know it's weird that we're talking about view as in V-U-E and I'm talking about view as in V-I-E-W. Does everyone have something that's working? What did I just break?
[25:53] Oh, I had an extra thing at the end. There we go. The next thing we're going to do is nested routes. In order to do that, we are going to take what we have in app, which is our router view, which is what defines our top-level component routing. We're going to take this same tag and put it inside blog JS, which will define a second routing option.
[26:40] Once we've done that, we want to be in our main.js file, where our routes are defined. Again, this is a situation where I'm going to introduce multiple options. They all do essentially the same thing. We're going to define children, which ends up being a parallel construct. It is an array with route records in it.
[27:08] The only difference is that it's a level below our top level. It'll go in the internal router view instead of the top-level router view, but the syntax and the way we define it is the same. I'm going to import something called guest post as another component that we can use, just because we're getting kind of duplicative.
[27:39] The first thing we're going to do is we're going to add a route record. Whoops. Path. I'm going to call it guest. The component is guest post. I can't do this because guest will be the ID. Remember that we are underneath an ID. We need to be two levels deep to add guest. This is the sub-route for guest posts. That's one way to do it.
[28:20] If this is too annoying or you have reason to want to access it directly, if you put a / on the front of this you can now access everything directly from your root level. What did I just break? There we go. No. What did I just break? Hold on. It might be hot relocate reloading. It happens occasionally. I'm just going to try that again.
[28:59] There we go. Live workshops are fun, everybody. Vue has really nice developer tools, in case anyone is curious about that. Router view is functional. What are our routes? /guest.
[29:33] What did I do? I genuinely don't know what I broke right here. What should be happening is that you should be able to navigate with this at the top level because we have a / right here. Why that isn't working, I genuinely do not know, which is always fun. I tested all this yesterday.
[30:04] If I send that back, that's fine. We can add guest. We see that working. That all goes away. That doesn't work. There we go. Must have been a hot reloading issue, or I spelled something wrong, which is always fun. If we add our /, it's going to override all of this and become...
[30:39] It's a sub-component, so we're seeing both of these things. It's a sub-route, but we are able to access it as a top-level path. Does that make sense?
[30:52] Lucas, you're getting an unexpected token right now from doing the /guest? Sorry, I just saw that, if you sent that a minute ago. Get back to me if you're still seeing that.
[31:08] The last thing we can do is we can remove our path entirely. What this does is it says this is always going to show up. It's basically providing a default for our sub navigation. We could still add additional paths and route records that would show up here and appear in here, but if we didn't include anything something still shows up. We've defined that based on that empty path.
[31:54] The last thing we can do is what we hinted at earlier, which is parallel routing. I'm going to define two routes here. They show up immediately. I'm going to give one of them a name. We're just going to call it "second." When I go back over to my children, I have to make one big change. I'm now pointing at components, which is itself an object.
[32:36] Default is my unnamed route. "Second" is my named route. Now I have two routes. If I wanted to make this Egghead, I could. You start to see that I can define multiple things inside of here. Lucas, I'm getting an unexpected token error right now.
[33:07] Unexpected token comma. Works with the curly braces. It's expecting a comma after the path. You mean here? Sorry. Can you paste your code? I'm just curious. May be a linter thing.
[33:31] One thing to keep in mind is that I could give both of these names. I could call it "first," and I could call it "second." Then I no longer need that default. The default is just for the unnamed one, which in most cases you'll want.
[33:47] Lucas, after component guest post, you need a comma. There's always commas at the end of these objects. I genuinely could not tell you why Vue enforces that, but it does.
[34:09] We're starting to see that we can have multiple views at the same time. They are defined roughly the same way that our top level is. Oh, you're right. Tyler found it. Children is just like your routes array, which means every route that you're defining is an object. It's a route record, so it needs those curly braces.
[34:40] I admit that they are a little harder to see here. Hopefully, my rainbow theme helps. I'm going to have to turn off a lot of plugins when I record these. Define whatever extra child paths you want to, however fancy or not fancy you want to get. As long as you have one set of sub-routing working, I will feel confident that you understand this.
[35:25] We're making very good time, which is nice.
Zach: [35:29] Is there a use case you want these parallel routes?
Laurie: [35:37] Off the top of my head, the one that comes to mind is that you have...This is not a very good use case. You could do gallery stuff in here. If you wanted to display different things based on tabs that are a little more resource-intensive and you don't want to load them all at once, you could make it lazy by enforcing them as sub-routes and just rendering them when you click on stuff.
[36:05] Keep in mind, actually, that you are not re-rendering your entire application always. You're re-rendering your application only when you substantially change routing. I'm going to show you what is the world's greatest thing, which is the Vue Router docs. Everyone should know the Vue Router docs. I read them cover to cover in preparation for this. Yes, I am that dorky.
[36:38] One of the things that they talk about early on, when they talk about history mode, is how things re-render. If you want a more extensive explanation of when you're doing reloading and when you're not, this is a good way to do it. Just because you change the URL does not mean you are reloading things.
[37:04] That's how Vue is so performant, but it also means that if you have things like component life cycle hooks, they're not going to trigger just because you changed your navigation path. Keep that in mind.
[37:20] You want to see blog view? Yeah.
[37:32] Yeah, you're looking for name as your key. Then whatever you want to name it is what ends up getting used by the components as the key. The value of this is actually the key inside components.
[37:49] Feel free to plug into chat if you want me to navigate back and forth between things. Most of our stuff is in main.js, but I recognize that there's little, tiny things like this which end up being the things that mess up.
Woman: [38:05] Can you go back to main.js?
Laurie: [38:12] Yup.
Woman: [38:15] Just scroll down just a bit.
Laurie: [38:17] Mm-hmm.
[38:27] I am going to take this as a good point to have a 10-minute break. Anyone who's still working can feel free to do so. I want people to be able to grab water or bathroom or whatever. We are about halfway through, but the stuff in the back half is more time-intensive.
[38:48] Depending on how we do, we will either have one more break or no more breaks. Make use of your time. We're going to keep this under two hours. I have faith in us. We don't need to keep you online for days. We don't need to keep Poppy being sad that she's all alone for days either. 1:50 and we'll all be back. Sound good? Cool.
Member comments are a way for members to communicate, interact, and ask questions about a lesson.
The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io
Be on-Topic
Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.
Avoid meta-discussion
Code Problems?
Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context
Details and Context
Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!