vue-router的原理和实现
vue-router原理
vue-router是实现了前端路由,也就是URL和UI之间的映射关系,当URL改变时会引起UI更新,但无需刷新页面。那么如何实现前端路由呢,也就是如何解决这两个问题:
- 如何改变URL但是页面不进行刷新
- 如何知道URL变化了
然后就引出hash和history两种实现方式解决上面两个问题。
hash实现
hash是URL中#后面那一部分,改变URL中的hash部分不会引起页面刷新,通过监听hashchange可以知道URL的变化,改变hashURL的方式有如下几种:
- 通过浏览器前进后退改变URL
- 通过a标签改变URL
- 通过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事件,它的特点如下:
- 通过浏览器前进后退改变URL时会触发popstate事件
- 通过pushState/replaceState或a标签改变URL不会触发popstate事件
- 可以通过拦截pushState和replaceState的调用和a标签的点击事件来监听URL的改变
- 通过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等等。这些等之后整理好了再来看。
行百里者半九十