Recently read some teaching, as their own summary. Vue- Router for low
The first step is analysis
- Vue-router is used as a plug-in. So one needs to be exposed
install
Methods, details refer tohere - In our ordinary use, we need to take the parameter, which is an object. The class of
constructor
You need to receive an object - Vue-router has two methods,
router-link
.router-view
Global registration is required - If you look at all the things he’s done,
- Listen for route changes
- Change the corresponding template rendering
- implementation
router-link
.router-view
These two methods
Step two, start building the framework
- I’ll start by creating a class called MyVueRouter, which has a constructor called MyVueRouter
options
The parameters. There are also three corresponding methods, executed separatelyThings in Step 4, or implementationinstall
methods
MyVueRouter class
let Vue // Define a Vue
class MyVueRouter {
constructor (options) { // A configuration item is accepted when the instance is created
this.$options = options
this.routeMap = {} // It will be said later
// React routing is strongly binding, which is different from the router in React
this.app = new Vue({
data: {
current: '/'
}
})
}
init () {
this.bindEvents() // Listen for URL changes, bind events
this.createRouterMap(this.$options) // Parse the route configuration
this.initComponent() // Implement the router-view components
}
bindEvents () { // Listen for URL changes
}
onHashChange () { // Parse the route configuration
}
createRouterMap (options) { // Implement the router-view components
}
initComponent () {
// router-link router-view
Vue.component('router-link', {}})// router-view
Vue.component('router-view', {}}Copy the code
To explain why new Vue() is used above, we need a value to record the current address bar, so we use the Vue feature here. This is why vue-router is only available in Vue and not in other languages
The install method
// as a creation
MyVueRouter.install = function (_vue) { // What is actually implemented as a plug-in is that this method returns a Vue instance during execution
Vue = _vue
Vue.mixin({ // Extend the component
beforeCreate () {
// This is the current Vue instance
if (this.$options.router) {
// Execute once after the component
Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
// Use the component
Vue.use(MyVueRouter)
Copy the code
The third step is the realization of specific methods
Note that only hash routes are implemented here
BindEvents method
So the first thing that this method does is it listens for url changes. Executes the specified method/function when the URL changes
bindEvents () {
// When listening to the page just opened, note the binding of this pointer
window.addEventListener('load'.this.onHashChange.bind(this))
// listen for the last url change
window.addEventListener('hashchange'.this.onHashChange.bind(this))}Copy the code
Common events url, you need to click here, note that do not need to add on
OnHashChange method
onHashChange () {
this.app.current = window.location.hash.slice(1) | |'/'
// Make it easy to see all changes printed in the log
console.log(this.app.current)
console.log(window.location.hash)
}
Copy the code
There is no explanation for this, but by changing the response of Vue, change current
Why do we start with the 1 bit?
Hash route. See print log for details
createRouterMap
Parses the route configuration so that one corresponds to the other
This is where the routeMap created above comes in handy
createRouterMap (options) {
options.routes.forEach(item= > {
this.routeMap[item.path] = item.component
})
}
Copy the code
Create key-value pairs that map Component to current
InitComponent method
Function to implement router-link,router-view these two methods
initComponent () {
// router-link router-view
Vue.component('router-link', {
props: { to: String },
render (createElement) {
// createElement tag Data (Optional) Children attrs Native HTML attribute this.$slots.default a text in the tag
return createElement('a', { attrs: { href: The '#' + this.to } }, [this.$slots.default])
// Return the Vnode virtual DOM}})// router-view
Vue.component('router-view', {
render: (h) = > { // the h createElement abbreviation uses the header function to change the this pointer
// Global component attributes change in relation to global vue
const comp = this.routeMap[this.app.current]
// comp gets the corresponding component
return h(comp)
}
})
}
Copy the code
router-link
For details on createElement, click here
For the Render function, click here
Start with global registration
Accept a parameter: {to: String}
This is what we usually use, but if we need to add more, we’ll just implement this one
<router-link to="/">Home</router-link>
The main function of router-link is to jump, so we create an A tag and configure the jump information to realize the jump
router-view
Notice that I’m using the arrow function here, not the normal function, for the purpose of solving the this pointing problem
There is no need to write props because no parameters are needed
We just need to get the current, get the template, and give it to createElement to render
Step 4 Complete code
import a from '. /.. /components/a'
import b from '. /.. /components/b'
// Configure the URL change route resolution component
class MyVueRouter {
constructor (options) { // A configuration item is accepted when the instance is created
this.$options = options
this.routeMap = {}
// React routing is strongly binding, which is different from the router in React
this.app = new Vue({
data: {
current: '/form'
}
})
}
init () {
this.bindEvents() // Listen for URL changes
this.createRouterMap(this.$options) // Parse the route configuration
this.initComponent() // Implement the router-view components
}
bindEvents () {
window.addEventListener('load'.this.onHashChange.bind(this))
window.addEventListener('hashchange'.this.onHashChange.bind(this))
}
onHashChange () {
this.app.current = window.location.hash.slice(1) | |'/'
console.log(this.app.current)
console.log(window.location.hash)
}
createRouterMap (options) {
options.routes.forEach(item= > {
this.routeMap[item.path] = item.component
})
}
initComponent () {
// router-link router-view
Vue.component('router-link', {
props: { to: String },
render (createElement) {
// createElement tag Data (Optional) Children attrs Native HTML attribute this.$slots.default a text in the tag
return createElement('a', { attrs: { href: The '#' + this.to } }, [this.$slots.default])
}
})
// router-view
Vue.component('router-view', {
render: (h) = > {
// h createElement abbreviation uses the header function to change this to refer to the global component in relation to the global vue
const comp = this.routeMap[this.app.current]
console.log(comp)
return h(comp)
}
})
}
}
// as a creation
MyVueRouter.install = function (Vue) {
// This method is actually executed as a plug-in
// Yes can receive a Vue instance
Vue.mixin({ // Extend the component
beforeCreate () {
// This is the current Vue instance
if (this.$options.router) {
// Execute once after the component
Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
Vue.use(MyVueRouter)
export default new MyVueRouter({
routes: [{path: '/'.name: 'A'.component: a
},
{
path: '/b'.name: 'B'.component: b
}
]
})
Copy the code
APP. Js code
<template>
<div id="app">
<router-link to="/">Home</router-link> |
<router-link to="/b">B</router-link> |
<router-view></router-view>
</div>
</template>
Copy the code