Today, with the rapid development of the front end, if you can't keep learning all the time, you will be eliminated soon. Share the relevant knowledge of Vue router principle implementation. Make a little progress every day.
1, Vue router Basics
**1,Vue. If the parameter passed in is a parameter of the function: * * directly received by the function; If it is an object, call the install method of the object.
2. When initializing a Vue instance, a router is passed in, and a router is generated in the Vue instance r o u t e and route and route and router attributes: r o u t e in Save Store Yes When front of road from gauge be , The current routing rules are stored in the route, The current routing rules are stored in the route, and the routing instance object is stored in the route. You can call some routing related methods.
**3. Steps for using Vue Router: * * create views, register routing plug-ins, create routing objects and configure routing rules, register router objects, use placeholders in the page, and create links.
4. Dynamic routing:
cosnt routes = [ { // Use dynamic routing path: '/detail/:id', name: 'Detail', // When props is enabled, the parameters in the URL will be passed to the component // Receive URL parameters through props in the build props: true, // Route lazy loading component: () => import('../views/Detail.vue') } ]
5. How to get route parameters in the component:
① Obtain the data {{$route.params.id}} through the current routing rules. This method is strongly dependent on routing. When using components, there must be a route to pass parameters.
② When props is enabled in the routing rule, the route will pass the parameters in the URL to the corresponding component, and the component can receive the props. This is the same as the value transmission method of parent-child components, which no longer depends on the route. props: ['id']
6. Nested routes:
cosnt routes = [ // Nested Route { path: '/', component: Layout, children: [ { path: '', name: 'Index', component: Index }, { // Path can use relative path or absolute path // path: '/detail/:id', path: 'detail/:id', name: 'Detail', props: true, component: () => import('../views/Detail.vue') } ] } ]
7. Programming navigation: replace/push/go
this.$router.replace('/login') will not record this history
this.$router.push({ name: 'Detail', params: { id: 1 } })
this.$router.go(-2). If - 1 is passed in, it is equivalent to this$ router. back()
2, Hash mode and History mode
1. Differences between Hash mode and History mode:
Differences in manifestations:
The Hash mode has #, and the Hash number is followed by the routing address
The History mode is an ordinary URL, which needs to be supported by the server
Principle difference:
The Hash pattern is based on anchor points and onhashchange events
The History pattern is based on the History API in HTML5
history. Pushstate(), which can only be supported after ie10 (no request will be sent, but the routing address will be changed and recorded in the history)
history.replaceState()
2. History mode
The server should return the index of the single page application except for the static resources html
When clicking on a hyperlink:
Click the hyperlink and call history Pushstate() changes the address in the browser's address bar, but does not send a request and stores the address in the history. These are done on the client.
When refreshing the browser:
The browser sends a request to the server. The requested address is the address in the address bar. If the server does not process this address, an error will occur; If the server supports History, when the server judges that the current routing address does not exist, it will index the home page of the single page application Html is returned to the browser. After receiving the page, the browser determines the routing address, and then loads the corresponding component content for rendering
Three. Simulation implementation of Vue Router
1. Vue pre knowledge:
Plug in, mixed in, Vue Observable (), slot, render function, runtime and full version of Vue
2. Implementation principle of Vue Router
Hash mode:
① The content behind # in the URL is used as the path address. If only the address behind # is changed, the browser will not send a request and will record this address in the browser access history;
② Listen for hashchange events. When the hash is changed, the hashchange event will be triggered and the current routing address will be recorded;
③ Find the corresponding component according to the current routing address and re render.
History mode:
① Through history The pushstate () method changes the address bar. It only changes the address and records the routing address without sending a request
② By listening to the pop state event, you can listen to the changes of the browser operation and record the changed address. It will not be triggered when calling pushState or replaceState. The browser's forward and backward buttons or back and forward methods will be triggered
③ Find the corresponding component according to the current routing address and re render
3. Vue Router core code
// Register plug-ins // Vue.use() internally calls the install method of the incoming object Vue.use(VueRouter) // Create routing object const router = new VueRouter({ routes: [ { name: 'home', path: '/', component: homeComponent } ] }) // Create Vue instance and register router object new Vue({ router, render: h => h(App) }).$mount('#app')
4. Realization idea
① Create vueroter plug-in and use the static method install
Determine whether the plug-in has been loaded
When Vue is loaded, mount the incoming router object on the Vue instance (Note: only execute once)
② Create vueroter class
Initialization, options, routeMap, data (simplify operation, create Vue instance as responsive data, record the current path)
Create a route map, traverse all route information, and record the mapping of components and routes into the routeMap object
Create router link and router view components
When the path changes, find the corresponding component in the routerMap object through the current path and render the router view
Register the pop state, hashchange and load events. When the routing address changes, re record the current path
5. Code implementation
① Create vueroter plug-in
static install (Vue) { // When this method is called, the Vue constructor is passed in // 1. Determine whether the current plug-in has been installed if (VueRouter.install.installed) return VueRouter.install.installed = true // 2. Record Vue constructor to global variable _Vue = Vue // 3. Inject the router object passed in when creating the Vue instance into the Vue instance // Mixed in, all Vue instances and components will execute this method _Vue.mixin({ beforeCreate() { if (this.$options.router) { // This attribute is only available in the Vue instance option, and the component does not _Vue.prototype.$router = this.$options.router // Initialization components, routing map and event registration are implemented in sections 3, 4 and 5 this.$options.router.init() } } }) }
② Implementation constructor
constructor (options) { // Initialize three properties this.options = options this.routeMap = {} this.data = _Vue.observable({ // The data attribute is responsive and automatically updates the view when the route changes current: '/' }) }
③ Implement createroutema()
creatRouteMap () { // Create routing map // Traverse all routing rules, parse the routing rules into key value pairs and store them in routeMap this.options.routes.forEach(route => { this.routeMap[route.path] = route.component }) }
④ Implement router link and router view components
// Build versions of Vue include runtime version and full version // Runtime version: template template is not supported. It needs to be compiled in advance when packaging // Full version: including runtime and compiler. The volume is about 10KB larger than the runtime version. When the program runs, the template is converted into render function initComponents () { // Create two components, router link and router view _Vue.component('router-link', { props: { to: String }, // 1 - full version of Vue -- need to be in Vue config. JS to configure runtimeCompiler: true to automatically parse the template into render function // template: "<a :href='to'><slot></slot></a>" // 2 - Vue at runtime -- use render function directly render (h) { // The h function receives three parameters. The first one is to generate the header of the dom element, the second is to set some options, and the third is the content return h('a', { attrs: { href: this.to }, on: { click: this.handleClick } }, [this.$slots.default]) }, methods: { handleClick(e) { // pushState receives three parameters, 1 - event object, 2 - Web page title, 3 - address of hyperlink jump in history.pushState({}, '', this.to) this.$router.data.current = this.to // Cancel the default behavior of a tag to prevent page refresh from sending a request to the server e.preventDefault() } } }) const that = this _Vue.component('router-view', { render (h) { // Find the corresponding component according to the current path and pay attention to this problem const component = that.routeMap[that.data.current] return h(component) } }) }
⑤ Implement registration events
There are still some problems when the page is refreshed, backward, forward and the path changes
initEvents() { // Get the changed path in the current path and record it again window.addEventListener('hashchange', this.onHashChange.bind(this)) // Refresh button problem window.addEventListener('load', this.onHashChange.bind(this)) // Forward and backward button problem window.addEventListener('popstate', this.onHashChange.bind(this)) }
⑥ Implement init()
// It is convenient to initialize when mixing init() { this.creatRouteMap() this.initComponents() this.initEvents() }
be careful:
Projects created by Vue cli default to the runtime version of Vue js
If you want to switch to Vue with compiler version JS, you need to modify the Vue cli configuration
Create Vue. From the project root directory config. JS file, add runtimeCompiler
module.exports = { runtimeCompiler: true }
6. Specific source code
let _Vue = null export default class VueRouter { static install (Vue) { // When this method is called, the Vue constructor is passed in // 1. Determine whether the current plug-in has been installed if (VueRouter.install.installed) return VueRouter.install.installed = true // 2. Record Vue constructor to global variable _Vue = Vue // 3. Inject the router object passed in when creating the Vue instance into the Vue instance // Mixed in, all Vue instances and components will execute this method _Vue.mixin({ beforeCreate() { if (this.$options.router) { // This attribute is only available in the Vue instance option, and the component does not _Vue.prototype.$router = this.$options.router this.$options.router.init() } } }) } constructor (options) { // Initialize three properties this.options = options this.routeMap = {} this.data = _Vue.observable({ // The data attribute is responsive current: '/' }) } init() { this.creatRouteMap() this.initComponents() this.initEvents() } creatRouteMap () { // Create routing map // Traverse all routing rules, parse the routing rules into key value pairs and store them in routeMap this.options.routes.forEach(route => { this.routeMap[route.path] = route.component }) } // Build version of Vue // Runtime version: template template is not supported. It needs to be compiled in advance when packaging // Full version: including runtime and compiler. The volume is about 10KB larger than the runtime version. When the program runs, the template is converted into render function initComponents () { // Create two components, router link and router view _Vue.component('router-link', { props: { to: String }, // 1 - full version of Vue -- need to be in Vue config. JS to configure runtimeCompiler: true to automatically parse the template into render function // template: "<a :href='to'><slot></slot></a>" // 2 - Vue at runtime -- use render function directly render (h) { // The h function receives three parameters. The first one is to generate the header of the dom element, the second is to set some options, and the third is the content return h('a', { attrs: { href: this.to }, on: { click: this.handleClick } }, [this.$slots.default]) }, methods: { handleClick(e) { // pushState receives three parameters, 1 - event object, 2 - Web page title, 3 - address of hyperlink jump in history.pushState({}, '', this.to) this.$router.data.current = this.to // Cancel the default behavior of a tag to prevent page refresh from sending a request to the server e.preventDefault() } } }) const that = this _Vue.component('router-view', { render (h) { // Find the corresponding component according to the current path and pay attention to this problem const component = that.routeMap[that.data.current] return h(component) } }) } initEvents() { // For the problem of path change, retrieve the current path and record it in the current in data window.addEventListener('hashchange', this.onHashChange.bind(this)) // Refresh button problem window.addEventListener('load', this.onHashChange.bind(this)) // Forward and backward button problem window.addEventListener('popstate', this.onHashChange.bind(this)) } // Retrieve the current path and record it to the current in data onHashChange() { this.data.current = window.location.pathname || '/' } }