J-DuYa / DY-Book

迁移知识点
2 stars 1 forks source link

Vue-router 底层实现 #25

Open J-DuYa opened 9 months ago

J-DuYa commented 9 months ago

Vue-router

history 路由,为什么通过 nginx 会出现 404 的情况

Vue.js 使用的前端路由,分两种模式 historyhash 格式的。如果使用的是 history 模式,并且没有配置正确的路由重写规则,就会出现 404 错误。

在 nginx 的配置文件中,需要添加一个路由重写规则,将所有请求都重定向到 Vue.js 的入口文件(通常是 index.html。这样 Vue.js 就能正确的处理请求了。

server {
  ...
  location / {
    try_files $uri $uri/ /index.html
  }
  ...
}

hash 模式和 histroy 模式的区别

  1. hash 路由是通过 hash 来实现路由。在 vue 中是通过 mode: 'hash' 来设置。这种路由模式在早期的前端单页面应用中比较流行,因为它可以避免页面刷新,从而提升用户体验。但是也存在一些问题,比如 url 不够美观,不利于 SEO。

  2. history 路由是通过 h5 histroy api 进行实现。这种路由方式相对 hash 模式更有可读性和可维护性。更具备传统 url 规范,但是需要注意的是,请确保服务端的配置文件正确(ngInx),因为如果配置不好的好,就会出现 404 问题。

说一下 hash 模式和 histroy 模式的具体实现原理

  1. hash

    class HashHistory extends History {
    setupListeners () {
    if (this.listeners.length > 0) {
      return
    }
    
    const router = this.router
    const expectScroll = router.options.scrollBehavior
    const supportsScroll = supportsPushState && expectScroll
    
    if (supportsScroll) {
      this.listeners.push(setupScroll())
    }
    
    const handleRoutingEvent = () => {
      const current = this.current
      if (!ensureSlash()) {
        return
      }
      this.transitionTo(getHash(), route => {
        if (supportsScroll) {
          handleScroll(this.router, route, current, true)
        }
        if (!supportsPushState) {
          replaceHash(route.fullPath)
        }
      })
    }
    const eventType = supportsPushState ? 'popstate' : 'hashchange'
    window.addEventListener(
      eventType,
      handleRoutingEvent
    )
    this.listeners.push(() => {
      window.removeEventListener(eventType, handleRoutingEvent)
    })
    }
    }
  2. histroy 模式

    window.addEventListener('popstate', handleRoutingEvent)
    this.listeners.push(() => {
    window.removeEventListener('popstate', handleRoutingEvent)
    })

vue-router 中有哪些传参方式

query

this.$route.push({ path: 'xxx', query: { x: xxx }, })

params

// 第一种
this.$route.push({ name: 'xxx', params: { id: xxx }, })
// 第二种
this.$route.push({ path: `/param/${id}` })