Narutocc / Vue

:smirk_cat:Vue is a progressive framework for building user interfaces. Vue is also perfectly capable of powering sophisticated Single-Page Applications when used in combination with modern tooling and supporting libraries.
1 stars 0 forks source link

实现一个SPA #99

Open Narutocc opened 3 years ago

Narutocc commented 3 years ago

原理

1. 监听地址栏中hash变化驱动界面变化 2. 用pushsate记录浏览器的历史,驱动界面发送变化

步骤:

检测hash或者pushstate变化 -- 以当前hash为索引,加载对应资源 -- 等待资源加载完毕,隐藏之前的界面,执行回调 -- 显示当前界面,点击界面按钮或者浏览器回退/前进按钮触发hash变化

实现

hash 模式 核心通过监听url中的hash来进行路由跳转

// 定义 Router
class Router {
    constructor () {
        this.routes = {}; // 存放路由path及callback
        this.currentUrl = '';

        // 监听路由change调用相对应的路由回调
        window.addEventListener('load', this.refresh, false);
        window.addEventListener('hashchange', this.refresh, false);
    }

    route(path, callback){
        this.routes[path] = callback;
    }

    push(path) {
        this.routes[path] && this.routes[path]()
    }
}

// 使用 router
window.miniRouter = new Router();
miniRouter.route('/', () => console.log('page1'))
miniRouter.route('/page2', () => console.log('page2'))

miniRouter.push('/') // page1
miniRouter.push('/page2') // page2

history模式 history 模式核心借用 HTML5 history api,api 提供了丰富的 router 相关属性 先了解一个几个相关的api history.pushState 浏览器历史纪录添加记录 history.replaceState修改浏览器历史纪录中当前纪录 history.popState 当 history 发生变化时触发

// 定义 Router
class Router {
    constructor () {
        this.routes = {};
        this.listerPopState()
    }

    init(path) {
        history.replaceState({path: path}, null, path);
        this.routes[path] && this.routes[path]();
    }

    route(path, callback){
        this.routes[path] = callback;
    }

    push(path) {
        history.pushState({path: path}, null, path);
        this.routes[path] && this.routes[path]();
    }

    listerPopState () {
        window.addEventListener('popstate' , e => {
            const path = e.state && e.state.path;
            this.routers[path] && this.routers[path]()
        })
    }
}

// 使用 Router

window.miniRouter = new Router();
miniRouter.route('/', ()=> console.log('page1'))
miniRouter.route('/page2', ()=> console.log('page2'))

// 跳转
miniRouter.push('/page2')  // page2