前端路由基本实现原理

162 阅读1分钟

前端路由的实现分为:Hash和History的形式

Hash形式

手动改变路径的hash值、并监听hashchange操作,展示不同内容

实现

  • html
<ul>
    <li><a href='#/main'>main</a></li>
    <li><a href='#/person'>person</a></li>
</ul>
<div id="viewContent"></div>
  • js
/* DOMContentLoaded:当初始的 HTML 文档被完全加载和解析完成之后,
DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完全加载*/
window.addEventListener('DOMContentLoaded', changeView)  // 首次匹配

window.addEventListener('hashchange', changeView);  // 监听hash改变

var viewContent = document.querySelector("#viewContent");
function changeView() {
    switch (location.hash) {
        case '#/main':
            viewContent.textContent = 'main'
            break;
        case '#/person':
            viewContent.textContent = 'person'
            break;
        default:
            viewContent.textContent = ""
    }
}

History形式

利用HTML5中pushState、replaceState,不进行页面的刷新跳转,手动更改视图

API说明

history.pushState(state, title[, url])

  • 向当前浏览器会话的历史堆栈中添加一个状态
  • 参数:
  1. state: JavaScript对象,状态对象(popstate事件回调中能拿到)
  2. title: 标题,一般设置为""
  3. url: 新历史记录条目的URL

history.replaceState(stateObj, title[, url])

  • 修改当前历史记录实体
  • 参数:
  1. state: JavaScript对象,状态对象(popstate事件中能拿到)
  2. title: 标题,一般设置为""
  3. url: 新历史记录条目的URL

popstate 注意的是调用history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()或者history.forward()方法)

实现

  • html
<ul>
    <li><a href='/main'>main</a></li>
    <li><a href='/person'>person</a></li>
</ul>
<div id="viewContent"></div>
  • js
var ul = document.querySelector("ul");
var viewContent = document.querySelector("#viewContent");
window.addEventListener('DOMContentLoaded', onDOMContentLoaded);

// window.addEventListener('popstate', onPopState);
function onDOMContentLoaded(){
    ul.addEventListener("click",(event)=>{
        if(event.target.nodeName === 'A'){
            event.preventDefault();   // 阻止默认跳转事件
            history.pushState(null, "", event.target.getAttribute('href'))
            changeView();  // 改变视图
        }
    })
}
	   
function changeView(event) {
        console.log("changeView",event);
    switch (location.pathname) {
        case '/main':
            viewContent.textContent = 'main'
            break;
        case '/person':
            viewContent.textContent = 'person'
            break;
        default:
            viewContent.textContent = ""
    }
}