從Vue-router到html5的pushState

最近在用vue的時候忽然想到一個問題javascript

首先,咱們知道vue實現的單頁應用中通常不會去刷新頁面,由於刷新以後頁面中的vuex數據就不見了。 其次,咱們也知道通常狀況下,url變動的時候,好比指定location.href、history.push、replace等,頁面就會刷新。html

那麼問題來了,vue頁面的頁面跳轉時怎麼實現的?沒刷新頁面麼?沒刷新頁面,又要改變url,加載新內容怎麼作的?vue

去翻了一下vue-router的源碼,找到這樣一段html5

export class HTML5History extends History {
   ...

  push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    this.transitionTo(location, route => {
      pushState(cleanPath(this.base + route.fullPath))
      handleScroll(this.router, route, fromRoute, false)
      onComplete && onComplete(route)
    }, onAbort)
  }

  replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    this.transitionTo(location, route => {
      replaceState(cleanPath(this.base + route.fullPath))
      handleScroll(this.router, route, fromRoute, false)
      onComplete && onComplete(route)
    }, onAbort)
  }
  ...
}

再看看方法內部java

export function pushState (url?: string, replace?: boolean) {
  saveScrollPosition()
  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  const history = window.history
  try {
    if (replace) {
      history.replaceState({ key: _key }, '', url)
    } else {
      _key = genKey()
      history.pushState({ key: _key }, '', url)
    }
  } catch (e) {
    window.location[replace ? 'replace' : 'assign'](url)
  }
}

答案就是html5在history中新增長的方法:pushState和replaceState。這兩個又是幹啥的呢?(兩個十分相似,如下以pushState爲例說明,區別和push與replace一致)vue-router

HTML5的pushState()

首先看看這個是幹什麼的 pushState方法就是向history中push一條記錄,更改頁面url,可是不刷新頁面,不刷新頁面,不刷新頁面。不刷新頁面,這點很關鍵,這和下面的操做很類似vuex

window.location.href = window.location.href + '#a=b'

知道幹嗎的了,再看看API怎麼用的dom

history.pushState(state, title, url);
  • state是一個對象,具體內容除了最大640KB以外沒有別的限制,好比在vue中是生成了一個key存進去了。若無特殊須要傳個null便可。這個state能夠在history或者popstate的事件中看到 history中的 popstate中的 this

  • title這個參數目前沒什麼用處,多是給之後預留的參數,暫時用null就行了url

  • url很明顯,就是替換後的url了。url能夠接受絕對地址和相對地址,設置絕對地址的時候,要保證域名和當前域名一致,不然彙報以下錯誤

Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'https://www.baidu.com/' cannot be created in a document with origin 'https://mocard-aliyun1.chooseway.com:8443' and URL 'https://mocard-aliyun1.chooseway.com:8443/views/h5/indexasdasd'.
    at History.pushState (https://aixuedaiimg.oss-cn-hangzhou.aliyuncs.com/static/m/js/alog/v1.0.0/alog.min.js:1:23259)
    at <anonymous>:1:9

HTML5的popstate()

  • popstate與pushState相對應,主要在頁面url變動的時候觸發,通常綁定在window對象下
window.addEventListener('popstate', e => {
  console.log('popstate', )
})

前面pushState中傳入的state對象,能夠在這邊接收到,並根據須要去作一些處理。

說到這,vue-router是怎麼實現頁面「刷新」但不刷新的就知道了吧。 vue-router就是利用pushState這個屬性,在頁面前進的時候動態改變history的內容,添加一條記錄,接着location跟着改變。同時根據router前往的路由獲取對應的js資源文件並掛載到目標dom上實現頁面內容的更新,可是頁面自己並無刷新。

相關文章
相關標籤/搜索