Studio 11
Part 1: Components and Routing
In this studio you will be implementing client-side routing as discussed in this week's lecture on single page applications.
To get started, clone the starter code for this studio.
The starter app includes two components for you in the home and chat directories.
These include very little functionality, they are just
here as placeholders to represent two pages of your app.
Take a look at all of thes files to get a sense of how things are wired together.
Currently, the main app loads the <home> component and displays it.
While it it possible to implement routing manually using window.location.hash and window.onhashchange, as demonstrated in lecture, it can be a lot of work to get all the details right and it requires a lot of repetitive boilerplate.
Therefore, we're going to use a higher level routing library called Vue Router. This library provides a method createRouter as well as the components <router-view> and <router-link> that we will use to implement routing in our app.
Step 1: Adding a home route.
We have included some basic boiler plate in index.html,
that installs the router into Vue, but it is up to you to configure it.
Start by modifying the routes property,
which is a mapping from URL paths to components.
Start by just defining a single route for the home page that displays the <home> component in the route "/".
const router = createRouter({
history: createWebHashHistory(),
routes: [
{ path: "/", component: loadComponent("home") },
]
});
Once that is done,
change the <home></home> component in index.html to
<router-view></router-view>. The <router-view> component provided by Vue Router will
display whatever component matches the current path.
If you do everything right, nothing should change!
This is because currently our router only includes one route, which is
the <home> component that we had before.
Step 2: Adding a chat route.
Now things are going to get more interesting. Let's add another route
that maps paths of the form /chat/:chatId to the <chat> component.
Note that the notation :chatId, means that part of the path is a variable,
that will be passed to the Chat component as a prop.
The added route should look like this, with props set to true so that the chatId is passed as a prop to the component.
{ path: "/chat/:chatId", component: loadComponent("chat"), props: true },
Next, go into the home/index.html file and make each chat in the list link
to its corresponding page with the <router-link> component.
<router-link :to="`/chat/${chatId}`"> Chat #{{ chatId }} </router-link>
Try it out!
- Does the content change to display the current chat?
- Does the URL change to reflect the current chat?
- Do you stay on a particular chat page when you refresh the page or copy the URL into a different tab?
Step 3: Adding a back button.
Once you enter a chat, you currently can't get back without
going and clicking the browser's back button or manually changing the URL.
It is nice that you now support these, but your app should also provide
a way to go back on its own without these external tools.
Add a <router-link> component with an appropriate path to make the title ("My Single Page Chat App") always take you back to the home page---a very common design pattern.
Step 4: Adding a "profile" page
Create a new profile component and give it the route /profile.
Like the home and chat components, the component can just
be a placeholder that says "This is a profile".
Then use <router-link> to add a link to the profile page. Place this link within the <header> in index.html so that the link is visible on all pages.
Step 5: Signifying the current page
Currently, when the user clicks on links between pages they get indirect feedback that the navigation suceeded from the page content and URL changing. We can make the UI a little better by also providing direct feedback that is localized to the links the user is clicking.
To do this, we are going to implement a common pattern where links to the current page are displayed differently from other pages. Therefore, when a user clicks on a link it will appear to stay "pressed". This gives the user feedback that they have successfully navigated to the given page and it is easy to see what page is currently visited at a glance.
Since this is a very common pattern, the Vue Router package automatically adds the class
router-link-active to <router-link> components that
point to the current page.
Use CSS to style the router-link-active class to indicate
to the user which page they are on:
a.router-link-active {
color: black;
text-decoration: none;
}