1. 程式人生 > 其它 >vue-router的原理和實現

vue-router的原理和實現

我之前寫了一半了,居然又沒見了就離譜,從頭開始。

vue-router原理

vue-router是實現了前端路由,也就是URL和UI之間的對映關係,當URL改變時會引起UI更新,但無需重新整理頁面。那麼如何實現前端路由呢,也就是如何解決這兩個問題:

  1. 如何改變URL但是頁面不進行重新整理
  2. 如何知道URL變化了
    然後就引出hash和history兩種實現方式解決上面兩個問題。

hash實現

hash是URL中#後面那一部分,改變URL中的hash部分不會引起頁面重新整理,通過監聽hashchange可以知道URL的變化,改變hashURL的方式有如下幾種:

  1. 通過瀏覽器前進後退改變URL
  2. 通過a標籤改變URL
  3. 通過window.location改變URL
    然後監聽hash的變化是hashchange
    那麼我們來簡單的實現一下hash去改變URL並且直接更新UI。
  <style>
    .routeView {
      color: pink;
    }
    .routeView2 {
      color: skyblue;
    }
  </style>
</head>
<body>
  <ul>
    <li><a href="#/home">home</a></li>
    <li><a href="#/cart">cart</a></li>
    <li><a href="#/user">user</a></li>
  </ul>
  <div class="routeView"></div>
  <div class="routeView2"></div>
</body>
<script>
  let routeView = document.querySelector('.routeView')
  let routeView2 = document.querySelector('.routeView2')
  //監聽URL的改變
  window.addEventListener('hashchange', () => { 
    routeView.innerHTML = location.hash //將URL顯示到routeView中
  })
  // 監聽UI的重新渲染
  window.addEventListener('DOMContentLoaded', () => {
    if(!location.hash) {
      location.hash =  '/'
    } else {
      routeView2.innerHTML = location.hash
    }
  })
</script>

然後我們可以發現,當URL改變的時候,UI介面確實發生了更新,但是整個介面並沒有重新渲染。冰狗,完美完成任務。

history實現

history改變URL的方法有如下兩種:
pushState,改變URL後可以記錄之前到過的URL
replaceState,不會記錄之前到過的URL
history監聽URL改變的方法popstate事件,它的特點如下:

  1. 通過瀏覽器前進後退改變URL時會觸發popstate事件
  2. 通過pushState/replaceState或a標籤改變URL不會觸發popstate事件
  3. 可以通過攔截pushState和replaceState的呼叫和a標籤的點選事件來監聽URL的改變
  4. 通過js呼叫history的back,go,forward方法可以觸發該事件
    既然懂了,那就讓我們來完美的實驗一下如何用history完成前端路由:
<!DOCTYPE html>
<html lang="en">
<body>
<ul>
    <ul>
        <li><a href='/home'>home</a></li>
        <li><a href='/about'>about</a></li>

        <div id="routeView"></div>
    </ul>
</ul>
</body>
<script>
    let routerView = routeView
    window.addEventListener('DOMContentLoaded', onLoad)
    window.addEventListener('popstate', ()=>{
        routerView.innerHTML = location.pathname
    })
    function onLoad () {
        routerView.innerHTML = location.pathname
        var linkList = document.querySelectorAll('a[href]')
        linkList.forEach(el => el.addEventListener('click', function (e) {
            e.preventDefault()
            history.pushState(null, '', el.getAttribute('href'))
            routerView.innerHTML = location.pathname
        }))
    }

</script>
</html>


(ps:id選擇器可以直接獲取,然後是拿到了window上面

自己實現vue-router

自己做一個vue的外掛,還是很特別的,首先我們知道使用vue-router的話我們是如下這樣簡單使用的:

//index.js中
import vueRouter from 'vue-router'

const routes = [{path: '', component: ''}]

const router = new vueRouter({
  mode: 'history',
  routes
})

export default router

//main.js中
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.use(router)

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

因為使用到new去new一個vueRouter,所以可以把它當作一個類,其次用到了Vue.use(),所以必須要有install方法,那我們來寫一個簡單的:

class myRouter() {
}

myRouter.install = function() {}

export default myRouter;

歐克,寫完了,鳴金收兵。hhh,開玩笑的。
然後我們知道vue-router有許多的內建方法,如push,go,replace等等。這些等之後整理好了再來看。