手写前端路由

169 阅读1分钟

1. 原生js实现前端路由

  • h5模式(history)实现:先收集,再利用pushState执行。
// html
<div id="container">
        <a href="./">首页</a>
        <a href="./user">用户</a>
        <a href="./home">家里</a>
</div>
<div id="content"></div>
// js 
class BaseRouter {
    constructor(){
        this.routes = {}
        this._bindPopState()
    }
    // 收集所有的路由
    route(path,func) {
        this.routes[path] = func || function(){}
    }
    // 路由跳转的go方法
    go(path) {
        // 添加路径
        window.history.pushState({path}, null, path)
        // 执行回调函数
        const func = this.routes[path]
        if(func) func()
    }
    // 每次popState调用时会更新界面(浏览器的前进后退)
    _bindPopState(){
        window.addEventListener('popstate',e => {
            console.log('popstate调用了');
            const path = e.state && e.state.path
            const func = this.routes[path]
            if(func) func()
        })
    }
}

const Route = new BaseRouter()
Route.route('./',() => changeText('我在首页'))
Route.route('./user',() => changeText('我在用户页'))
Route.route('./home',() => changeText('我在家里'))

// 定义修改内容的函数,在vue中相当于绑定组件的感觉
function changeText(params) {
    document.getElementById('content').innerHTML = params
}

// 给a标签添加点击事件完成路由跳转
document.getElementById('container').addEventListener('click',(e)=>{
    if(e.target.tagName === 'A') {
        e.preventDefault()
        Route.go(e.target.getAttribute('href'))
    }
})
  • hash模式实现:先收集,再利用hashchange实现。
// html
<div id="container">
    <a href="#">首页</a>
    <a href="#user">用户</a>
    <a href="#home">家里</a>
</div>

// js
class BaseRouter {
    constructor(){
        this.routes = {}
        this.refresh = this.refresh.bind(this)
        // hashchange方法调用即执行路由跳转
        window.addEventListener('hashchange',this.refresh)
        // 加载过程中也要执行
        window.addEventListener('load',this.refresh)
    }
    // 收集所有的路由
    route(path,func) {
        this.routes[path] = func || function(){}
    }
    // 执行路由跳转的方法
    refresh(){
        const path = `/${window.location.hash.slice(1) || ''}`
        this.routes[path]()
    }
}

const Route = new BaseRouter()
Route.route('/',() => changeText('我在首页'))
Route.route('/user',() => changeText('我在用户页'))
Route.route('/home',() => changeText('我在家里'))

// 定义修改内容的函数,在vue中相当于绑定组件的感觉
function changeText(params) {
    document.getElementById('content').innerHTML = params
}