一文搞懂vue-router、react-router

385 阅读5分钟

一、window.history.pushState

1.说明

window.history.pushState方法用于向浏览器历史栈中添加一个状态。

2.语法:

window.history.pushState(state, title, url);

3.参数说明:

  • state:一个对象,用于保存状态信息,可以通过history.state属性获取该状态信息。
  • title:一个字符串,表示新的页面标题,目前大部分浏览器忽略该参数。
  • url:一个字符串,表示新的URL,可以是绝对路径或相对路径。

4.使用示例:

window.history.pushState({page: 1}, "Page 1", "page1.html");

上述示例将一个新的状态对象{page: 1}添加到浏览器历史栈中,并且将浏览器URL修改为"page1.html"。

5.注意事项:

  • 调用pushState方法不会触发页面的刷新或跳转,只会修改浏览器URL和添加一个新的状态对象。
  • 修改URL后,可以通过window.onpopstate事件监听浏览器的前进后退操作,并根据新的状态对象进行相应的处理。
  • 使用pushState方法后,可以通过浏览器的前进后退按钮或JavaScript代码的history.back()、history.forward()等方法进行页面的切换。

6.state传参

可以通过state参数来实现路由传参。state参数可以是一个对象,可以在对象中添加需要传递的参数。

例如,假设我们需要在路由中传递一个id参数,可以这样使用:

window.history.pushState({id: 1}, "Page 1", "page1.html");

上述示例中,我们将一个包含id参数的对象{id: 1}作为state参数传递给pushState方法。

在接收参数的页面中,可以通过history.state来获取传递的参数:

js
console.log(history.state.id); // 输出 1

上述示例中,我们通过history.state.id来获取传递的id参数。

注意,使用pushState方法传递参数并不会触发页面的刷新或跳转,只会修改浏览器URL和添加一个新的状态对象。因此,在接收参数的页面中,需要通过监听浏览器的前进后退操作来处理参数的变化。可以通过window.onpopstate事件来监听浏览器的前进后退操作,并根据新的状态对象进行相应的处理。

二、history.pushState和Vue Router对比

1.共同点:

window.history.pushState和Vue Router都可以用于实现前端路由。

2.区别:

  • window.history.pushState是浏览器原生提供的API,用于修改浏览器URL和添加一个新的状态对象到浏览器历史栈中。它可以实现无刷新的页面切换,并且可以传递参数。但是,它只提供了基本的路由功能,需要手动监听浏览器的前进后退操作,并进行相应的处理。

  • Vue Router是Vue.js官方提供的路由插件,它提供了更丰富的路由功能和组件化的路由配置。它可以通过定义路由表、嵌套路由、动态路由等方式来配置路由,并且提供了路由导航守卫、路由过渡效果等功能。Vue Router可以更方便地管理页面的切换和传递参数,并且与Vue.js框架的其他特性更加紧密地结合在一起。

3.总结

window.history.pushState适用于简单的前端路由场景,而Vue Router适用于复杂的单页面应用(SPA)场景。如果项目使用Vue.js框架,推荐使用Vue Router来管理路由。

三、Vue Router 中 history 源码分析

1.说明:

Vue Router中的history路由跳转是通过调用浏览器原生的history.pushState方法实现的。

2.源码中的位置:

  • 在Vue Router的源码中,当进行路由跳转时,会调用push方法来进行跳转,该方法定义在src/history/base.js文件中:
js
export function push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  const { current: fromRoute } = this
  // ...
  const to = resolve(location, fromRoute, false, this)
  const { location: toRoute, route: toRouteRecord } = to

  const pushUrl = stringifyQuery(toRoute.fullPath)

  if (this.app) {
    const { scrollBehavior } = this.app.$options
    if (scrollBehavior) {
      handleScroll(this.router, toRoute, fromRoute, false)
    }
  }

  this.confirmTransition(
    to,
    () => {
      const { state } = this.history
      // ...
      this.transitionTo(toRoute, () => {
        pushState(cleanPath(this.base + pushUrl), onComplete, onAbort)
      })
    },
    err => {
      if (isNavigationFailure(err, NavigationFailureType.redirected) && err.to === this.current.fullPath) {
        // ...
        return
      }
      if (onAbort) {
        onAbort(err)
      }
    }
  )
}

在上述代码中,首先通过resolve方法将目标路由转换为实际的路由对象to。然后,调用stringifyQuery方法将目标路由的query参数转换为URL字符串。接着,通过pushState方法将新的URL添加到浏览器历史栈中。

  • pushState方法的具体实现可以在src/history/html5.js文件中找到:
js
function pushState (url?: string, replace?: boolean) {
  const history = window.history
  try {
    if (replace) {
      // ...
      history.replaceState(state, '', url)
    } else {
      // ...
      history.pushState(state, '', url)
    }
  } catch (e) {
    // ...
  }
}
  • 在上述代码中,通过调用history.pushState方法将新的URL添加到浏览器历史栈中。通过replace参数来控制是使用pushState还是replaceState方法,replace为true时使用replaceState方法,replace为false时使用pushState方法。

3.Vue Router 中路由传参的quary和param的区别

1)说明:

在Vue Router中,路由传参可以使用query和params两种方式。

2)使用方式:
  • query参数是通过URL中的查询字符串传递的,

  • 即在URL后面添加?param1=value1&param2=value2。

  • query参数可以在路由跳转时通过route.query对象获取,也可以在组件中通过this.route.query获取。

  • params参数是通过URL路径中的占位符传递的,

  • 即在路由配置中使用/:param1/:param2的形式定义。

  • params参数可以在路由跳转时通过route.params对象获取,也可以在组件中通过this.route.params获取。

3)区别:

传递方式不同:

  • query参数通过URL中的查询字符串传递,
  • params参数通过URL路径中的占位符传递。

使用方式不同:

  • query参数可以在route.query对象或this.route.query获取,
  • params参数可以在route.params对象或this.route.params获取。 传递的数据类型不同:
  • query参数可以传递任意类型的数据,
  • params参数一般用于传递动态路由参数,一般为字符串类型。

URL的形式不同:

  • query参数的URL形式为?key1=value1&key2=value2,
  • params参数的URL形式为/param1/param2。

总结:query参数适合传递较少的参数,而params参数适合传递较多或者动态的参数。