preface
From the previous section, we learned that there are two implementations of the front end reason, Hash routing and History routing, and used each to implement a front end route.
Let’s combine Vue with Hash routing to implement a very simple Vue-router.
Begin to implement
Imagine implementing a Vue-Router. How would you use it? Refer to the official vue-Router usage to see how HTML is used:
<div id="app">
<p>
<router-link to="# /">home</router-link>
<router-link to="#/book">book</router-link>
<router-link to="#/movie">movie</router-link>
</p>
<router-view></router-view>
</div>
Copy the code
There are two components that we need to implement: router-link and router-view. Let’s look at js again:
const Home = { template: '<div>home</div>' };
const Book = { template: '<div>book</div>' };
const Movie = { template: '<div>movie</div>' };
const routes = [
{ path: '/'.component: Home },
{ path: '/book'.component: Book },
{ path: '/movie'.component: Movie }
];
const router = new VueRouter(Vue, {
routes
});
new Vue({
el: '#app'
});
Copy the code
There will be our own defined components Home, Book, and Movie, with their respective routes. Our VueRouter implementation is different from the official VueRouter. When VueRouter is new, we pass Vue as an argument instead of injecting it to the root instance.
And then there’s the VueRouter implementation.
VueRouter
How to implement VueRouter
- The binding
hashchange
Event to realize front-end routing; - Make a route mapping between the incoming routes and components, and switch which route to find the corresponding component.
- You need a new Vue instance and you do responsive communication, when the route changes,
router-view
Responds to updates; - registered
router-link
和router-view
Components.
So let’s create a VueRouter:
class VueRouter {
constructor (Vue, options) {
this.$options = options; }}Copy the code
The binding event
Add a method to the VueRouter that binds to an event and fires the onHashChange method if the route changes.
constructor (Vue, options) {
this.init();
}
// Bind the event
init () {
window.addEventListener('load'.this.onHashChange.bind(this), false);
window.addEventListener('hashchange'.this.onHashChange.bind(this), false);
}
Copy the code
Route mapping table
Set the incoming options as a route mapping table so that you can find the corresponding component through the route.
constructor (Vue, options) {
this.$options = options;
this.routeMap = {};
this.createRouteMap(this.$options);
}
// Route mapping table
createRouteMap (options) {
options.routes.forEach(item= > {
this.routeMap[item.path] = item.component;
});
}
Copy the code
Options, the relationship between routing and components:
const routes = [
{ path: '/'.component: Home },
{ path: '/book'.component: Book },
{ path: '/movie'.component: Movie }
];
Copy the code
Generated routing mapping table:
this.routeMap = {
'/': Home,
'/book': Book,
'/movie': Movie
};
Copy the code
The response
We need to create a new Vue instance and store the current route in its data. When current is changed, the router-view will update the view itself.
constructor (Vue, options) {
this.app = new Vue({
data: {
current: '# /'}}); }// Get the current hash string
getHash () {
return window.location.hash.slice(1) | |'/';
}
// Set the current path
onHashChange () {
this.app.current = this.getHash();
}
Copy the code
If you use this.app.current in the router-view, it will be updated as soon as it is updated.
Certified components
Router-link is actually a tag that can be clicked to trigger a HashChange. Router-view implements a render method that takes the component of the current route and renders it.
constructor (Vue, options) {
this.initComponent(Vue);
}
// Register the component
initComponent (Vue) {
Vue.component('router-link', {
props: {
to: String
},
template: '<a :href="to"><slot></slot></a>'
});
const _this = this;
Vue.component('router-view', {
render (h) {
var component = _this.routeMap[_this.app.current];
returnh(component); }}); }Copy the code
The complete code
So, a simple vue-router is created. The entire code looks like this:
class VueRouter {
constructor (Vue, options) {
this.$options = options;
this.routeMap = {};
this.app = new Vue({
data: {
current: '# /'}});this.init();
this.createRouteMap(this.$options);
this.initComponent(Vue);
}
// Bind the event
init () {
window.addEventListener('load'.this.onHashChange.bind(this), false);
window.addEventListener('hashchange'.this.onHashChange.bind(this), false);
}
// Route mapping table
createRouteMap (options) {
options.routes.forEach(item= > {
this.routeMap[item.path] = item.component;
});
}
// Register the component
initComponent (Vue) {
Vue.component('router-link', {
props: {
to: String
},
template: '<a :href="to"><slot></slot></a>'
});
const _this = this;
Vue.component('router-view', {
render (h) {
var component = _this.routeMap[_this.app.current];
returnh(component); }}); }// Get the current hash string
getHash () {
return window.location.hash.slice(1) | |'/';
}
// Set the current path
onHashChange () {
this.app.current = this.getHash(); }}Copy the code
The last
Combining Vue with Hash routing, listening for hashChange events, and using Vue’s response mechanisms and components, you have a Vue-router implemented above.
All source reference here.