前端路由实现的关键知识点

哈希路由(Hash Routing)

哈希路由使用URL中的哈希部分(即#符号后面的部分)来控制页面内容的变化。这种方式的优点是不需要服务器端配置支持。

原理

  • 哈希部分的变化不会导致页面的重新加载,浏览器会触发hashchange事件。
  • 不管是直接在链接标签上指定<a href='#abc'>test</a>还是通过location.hash='#1234'设置hash都会导致浏览器地址栏变化,从而触发hashchange事件

  • 在前端路由中,监听hashchange事件,可通过event.newURL或location.hash来获取改变后的页面地址。
// 监听hash变化事件
window.addEventListener("hashchange", () => {
    const hash = window.location.hash.slice(1); // 获取#后面的路由路径
    renderPage(hash);
});

// 页面渲染函数
function renderPage(route) {
    if (route === "home") {
        document.getElementById("app").innerHTML = "<h1>Home Page</h1>";
    } else if (route === "about") {
        document.getElementById("app").innerHTML = "<h1>About Page</h1>";
    } else {
        document.getElementById("app").innerHTML = "<h1>Not Found</h1>";
    }
}

历史记录路由(History Routing)

历史记录路由使用HTML5的History API,通过操作浏览器的历史记录来实现路由。这种方式更贴近真实的URL结构,但需要服务器配置,以防止用户直接访问某个URL时服务器找不到对应的资源。

原理

  • history.pushState()history.replaceState():这些方法可以添加或替换历史记录条目,同时改变URL而不触发页面刷新。
  • popstate事件:用户点击浏览器的前进或后退按钮时会触发该事件,前端应用可以通过监听popstate事件来根据URL渲染不同的页面。
// 路由跳转函数
function navigateTo(route) {
    history.pushState(null, null, route); // 修改URL且不会刷新页面
    renderPage(route); // 渲染对应的页面内容
}

// 页面渲染函数
function renderPage(route) {
    if (route === "/home") {
        document.getElementById("app").innerHTML = "<h1>Home Page</h1>";
    } else if (route === "/about") {
        document.getElementById("app").innerHTML = "<h1>About Page</h1>";
    } else {
        document.getElementById("app").innerHTML = "<h1>Not Found</h1>";
    }
}

// 监听popstate事件,用于处理前进/后退
window.addEventListener("popstate", () => {
    renderPage(window.location.pathname);
});
  • 通过pushState/replaceState时 不会触发 popstate 事件。因此需要拦截 pushState/replaceState
window.history.pushState = new Proxy(window.history.pushState, {
    apply(target, thisBinding, args) {
        //下个页面的地址
        const nextPathName = args[2];
        // 继续执行原有的程序
        return target.apply(thisBinding, args);
    }
});

 

路由匹配核心原理

以一个最基本的react-router组件进行分析:

<Router history={hashHistory}>
  <Route path="/" component={App}/>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Router>

URL 变更 -> history 变化 -> location 变化 -> Router 组件收到新的 location,遍历Router子组件,取出Route.path的值用path-url-regexp进行匹配,如果匹配,则渲染component属性指定的组件

 

posted @ 2018-09-05 11:46  我是格鲁特  阅读(181)  评论(0)    收藏  举报