Vue 2 Internal Features from the Ground Up

Challenge 15: Solution

Evan You

Evan You

Creator of Vue.js
Vue 2 Internal Features from the Ground Up

Check out a free preview of the full Vue 2 Internal Features from the Ground Up course

The "Challenge 15: Solution" Lesson is part of the full, Vue 2 Internal Features from the Ground Up course featured in this preview video. Here's what you'd learn in this lesson:

Evan walks through the solution to Challenge 15.


Transcript from the "Challenge 15: Solution" Lesson

>> Evan You: So let's take a look at how to handle this dynamic segment. As mentioned just now, ideally we want to precompile the regular expressions that we need to use before the component is even rendered, because just from the performance perspective it's also better to precompile, because you don't want to recompile the regular expression of every single render on your app, right?

So let's take a look at the render function right here, we have the componentToRender and we have the props. The question is how do we figure out which component to use? The difference from the previous exercise is that our route table, we can no longer simply use a key, object key access check to determine if a component is matched or not.

In fact, we will never know unless we iterate through every possible key in the object until we find one that matches. So you can root force this. You can do something like object.keys routetable for each key. And then you can compile the regular expression here, and then try to see if it matches.

It'll work, but from a performance perspective it's not that efficient. So let's create something called a compiledRouteTable.
>> Evan You: We are gonna iterate through this raw routeTable which is essentially provided by our user. And for each path in the round table we will compile it. So now we can use path to regular expression path.

And remember we need the keys array to hold the dynamic segments.
>> Evan You: In fact, I would have just called them dynamic segments here so that it's clear what we're doing.
>> Evan You: And dynamic segment, okay, so we got the regular expression, we got the dynamic segments. And we also have a component = routeTable[path], right?

This is the component we want to render, so these three things are needed if we want to check if a raw incoming path matches a certain, to determine whether this component should be rendered given an incoming path. So, what we can do is on the compiled route table, we'll just store it.

In fact, this compile routeTable doesn't even need to be an object. It can be just an array, right? So compiled routes, even, it doesn't need to be an object. Compiled routes, push, component Regex and dynamicSegments.
>> Evan You: So, now we've created an array containing our route entries. Now, what we need to do inside our component here is instead of iterating to the thing, compiledRoutes dot.

We can do forEach, but we can also do some. This way we can terminate the iteration when we find a route that actually matches. So now we need to check if this is the path that we are getting, that we are currently at, and this where we need to figure out if this route somehow, this route and this path somehow they match, right?

And the way to find out is to do this.
>> Evan You: Right? So if there is a match,
>> Evan You: Then the component to render is obviously the component of this route.
>> Evan You: Right. And notice here, I have component to render here as well so if none of these routes exactly match then the component to render should proably be not found.

So we can initialize it here. Or we can initialize it to undefined and just fall back to not found here. Both are okay. And then another question is how do we extract the props to use here? So in fact, the answer is already here. In the comment, we have this piece of code.

>> Evan You: Actually, this is using the old API. So this is already sort of out of date on this library, but what you're gonna do, let's copy that piece of code and paste it here.
>> Evan You: And in fact you can just do this.
>> Evan You: You don't need to even reduce, you can just do dynamic segments are for each,

>> Evan You: index, props[key]
>> Evan You: Route.dynamicSegments.forEach, so it actually looks a bit different. So, route.dynamicSegments is going to be array that contains objects, okay so segment
>> Evan You: We want a, right? So set it on the props.
>> Evan You: And we also need the index here so that we can retrieve the corresponding value from,

>> Evan You: Well, dynamic segments, yeah, from the match result here, so the match will contain the
>> Evan You: Index + 1, remember to offset it by 1 because the first element in the match array will be the full matched path. Only starting from index 1 it's the dynamic segments value.

So now we've essentially completed the task. We've figured out which component we should render and we filled in the props object with the proper extracted dynamic segments if there are any. And we pass it along, and this should work. Yes?
>> Speaker 2: Why do you have a leading slash when you construct the path variable inside render.

Why you pre-pin that?
>> Evan You: That's because I think in the reference implementation we actually have a raw table that looks like this. All right, because in real route configuration most of the path you do start with a slash and because in some cases you might have nested configurations like this.

And you can even have children routes, like this. But that's sort of another topic. In fact, if you look at the Vue Router's configuration, it looks like this.
>> Evan You: ID, component, foo. And then it can have children, where you can nest them. So in children, you don't start the child path with a slash, so that this can be appended to this.

Because if you do this, this will be treated as like an absolute path, that's just, so this will be appended for you implicitly. So I think that this will be slightly different from the reference implementation. But let's hope it works.
>> Evan You: So,
>> Evan You: It works. Let's make it big.

>> Evan You: This foo and foo is not being properly separated. So let's make it more obvious. Add a new line here, and foo 123, foo 234.
>> Evan You: Okay, so notice that if we reload the page at foo 123, it instantly displays this instead of not found. And we can switch between them and we can also go to bar.

So now we've successfully created a semi-working routing system that can handle dynamic segments. And we are able to extract these dynamic segments and pass along them to route components as prompts. So the next step is handle nested routes. And that'll be tricky but I don't think we have time to go over that today.

Some other concerns are for example, how to extract this matching logic instead of having to write it in every app. You can extract this, the whole matching logic out into a component called router view, which is the component that we use in Vue Router. So you can essentially, in your app, you're just dropping this router view.

It'll figure out which component it should render at that place. And then we get something really close to what Vue Router actually looks like.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now