new Vue({
    router,
    render: h= > h(App)
}).$mount('#app')
Copy the code

Question: What is the purpose of the router passed in when creating a Vue instance?

  • Will givevueThe instance injects two properties
    • $routeRouting rules
    • $routerRoute objects

01 Dynamic Route

{
    path: '/detail/:id'.name: 'Detail'.// Enable props, which passes parameters in the URL to the component
    // Accept URL parameters in the component via props
    props: true.// route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () = > import(/* webpackChunkName: "detail" */ '.. /views/Detail.vue')}Copy the code
  • How to get this ID in the component
Method 1 Obtain data based on the current routing rule
$route.params.id

// Enable the props parameter in route rule 2
export default {
    props: ['id']}Copy the code

02 Nested routines by

// Nested by
  {
    path: '/'.component: Layout,
    children: [{name: 'index'.path: ' '.component: Index
      },
      {
        name: 'detail'.path: 'detail/:id'.props: true.component: () = > import('@/views/Detail.vue')}}]Copy the code

Programmatic navigation

Router.vuejs.org/zh/guide/es…

/ / string
router.push('home')

/ / object
router.push({ path: 'home' })

// Named route
router.push({ name: 'user'.params: { userId: '123' }})

// With query parameters, change to /register? plan=private
router.push({ path: 'register'.query: { plan: 'private' }})
Copy the code

HashHistoryPattern difference

Router.vuejs.org/zh/guide/es…

1. Differences in expression forms

  • HashModel –#
    • https://music.163.com/#/playlist?id=3102961863
  • HistoryMode – Requires server cooperation
    • https://music.163.com/playlist/3102961863

2. Principle difference

  • HashPatterns are based on anchor points, as wellonhashchangeThe event
  • HistoryPatterns are based onHTML5In theHistory API
    • History.pushstate () – supported only after IE10
    • history.replaceState()

The difference between pushState and push is that when we call push, the path changes and we send a request to the server. Calling pushState does not send a request, but simply changes the address in the browser’s address bar and records that address in history

3. HistoryUse of patterns

const router = new VueRouter({
    mode: 'history'.routes: []})Copy the code
  • HistoryServer support is required
  • Because in a single page application, the server doesn’t existhttp://www.testurl.com/loginSuch an address returns the page not found
  • So the server should return single-page applications except for static resourcesindex.html
HistoryPatterns ofNode.jsServer Configuration
const path = require('path')
// Import the module that handles history mode
const history = require('connect-history-api-fallback')
/ / import express
const express = require('express')

const app = express()
// Register the middleware that handles the history pattern
app.use(history())
// Static resource processing middleware, website root directory.. /web
app.use(express.static(path.join(__dirname, '.. /web')))

// Start the server on port 3000
app.listen(3000.() = > {
  console.log('Server on, port: 3000')})Copy the code
HistoryPatterns ofnginxServer Configuration
  • nginxServer Configuration (Windows)
    • Download from the official websitenginxThe package
    • Unzip the package to the c:\nginx-1.18.0 folder
    • Open the command line and switch to the directory C :\nginx-1.18.0
# start
start nginx
# to restart
nginx -s reload
# stop
nginx -s stop

# Handle history mode
location / {
  try_files $uri $uri/ /index.html;
}
# try_files means try to access the file
# $uri Specifies the path of the current request


Copy the code

Implementation principle of Vue Router

Vue pre-knowledge

  • The plug-in
  • Mixed with
  • Vue.observable()
  • slot
  • Render function
  • Run time and full Vue

1. Hashmodel

  • URL#The following content is the path address
  • Listening to thehashchangeThe event
  • Find the corresponding component based on the current routing address and re-render it

2. Historymodel

  • throughhistory.pushState()Method to change the address bar
  • Listening to thepopstateThe event
    • When callingpushstatereplacestateThe event is not triggered
    • It’s triggered by moving forward and backward
  • Find the corresponding component based on the current routing address and re-render it

3. Simulation implementation

To realize the router – the link

A build of Vue
  • Runtime version: Does not support template templates and is compiled ahead of time when packaging is required
  • The full version: contains the runtime and the compiler. It is about 10KB larger than the runtime version and converts the template into the render function when the program runs

The default for vuE-CLI creation is the runtime version

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

How to solve this problem?

  • Use the full versionVue
    • Cli.vuejs.org/zh/config/#…
// vue.config.js
module.exports = {
    runtimeCompiler: true
}
Copy the code
  • userender
initComponents (Vue) {
    // Create a router-link component
    Vue.component('router-link', {
      props: {
        to: String
      },
      render (h) {
        return h('a', {
          attrs: {
            href: this.to
          }
        }, [this.$slots.default])
      }
    })
  }
Copy the code

Implement the router – the view

initComponents (Vue) {
    // Create a router-link component
    Vue.component('router-link', {
      props: {
        to: String
      },
      render (h) {
        return h('a', {
          attrs: {
            href: this.to
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler (e) {
          history.pushState({}, ' '.this.to)
          this.$router.data.current = this.to
          e.preventDefault()
        }
      }
    })
    const self = this
    Vue.component('router-view', {
      render (h) {
        const component = self.routerMap[self.data.current]
        return h(component)
      }
    })
  }
Copy the code

Implement initEvent

initEvent () {
    window.addEventListener('popstate'.() = > {
      this.data.current = window.location.pathname
    })
  }
Copy the code

The complete code is as follows

let _Vue = null
class VueRouter {
  static install (Vue) {
    // 1. Check whether the plug-in is installed
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    // 2. Record the Vue constructor to the global variable
    _Vue = Vue
    // 3. Inject the router object passed into the Vue instance
    / / with
    _Vue.mixin({
      beforeCreate () {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }

  constructor (options) {
    this.options = options
    this.routerMap = {}
    this.data = _Vue.observable({
      current: '/'
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents(_Vue)
    this.initEvent()
  }

  createRouteMap () {
    // Iterate over all the routing rules, parse the routing rules into key-value pairs, and store them in the routeMap
    this.options.routes.forEach(route= > {
      this.routerMap[route.path] = route.component
    })
  }

  initComponents (Vue) {
    // Create a router-link component
    Vue.component('router-link', {
      props: {
        to: String
      },
      render (h) {
        return h('a', {
          attrs: {
            href: this.to
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler (e) {
          history.pushState({}, ' '.this.to)
          this.$router.data.current = this.to
          e.preventDefault()
        }
      }
    })
    const self = this
    Vue.component('router-view', {
      render (h) {
        const component = self.routerMap[self.data.current]
        return h(component)
      }
    })
  }

  initEvent () {
    window.addEventListener('popstate'.() = > {
      this.data.current = window.location.pathname
    })
  }
}

export default VueRouter

Copy the code