前端路由实现原理——hash模式和history模式

1 概述

前端路由是指,不同的url展示不同的页面,例如Vue React中,虽然是单页面,但是通过路由还是实现了我们想要的功能。
前端路由的模式分为两种:

  1. hash模式:http://localhost/Day/hash.html#/home 存在一个 # 符号,和普通的url相比有些丑
  2. history模式:http://localhost/home 这和普通的URL没有区别,非常好看
    那么这两种模式的实现原理是什么呢?

2. hash模式(简单一些)

主要使用:window.location.hash 和 onhashchange() 来实现的
实现的代码如下:需要在Apach服务下运行,具体的可以评论问我!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>hash</title>
</head>
<body>
    <button class="router" to="/home">首页</button>
    <button class="router" to="/content">内容</button>
    <div class="router-view">

    </div>

    <script>
        var btn=document.getElementsByClassName("router");
        var view=document.getElementsByClassName("router-view")[0];

        routes=[
            {
     
     "path":"/home", "component":"<p>我是首页的组件</p>"},
            {
     
     "path":"/content", "component":"<p>我是内容的组件</p>"}
        ]

        // 当hash值发生改变时,显示不同的内容  这是进入页面时触发的
        var hash=window.location.hash;
        if(hash){
     
     
            var url=hash.substring(1)
            renderView(url);
        }else{
     
     
            window.location.hash="/";
        }

        // 点击时,使得hash值发生改变,也就使得显示改变
        for(var i=0;i<btn.length;i++){
     
     
            btn[i].onclick=function(){
     
     
                var hash=this.getAttribute("to");
                renderView(hash);
            }
        }

        //hash值改变时  这是hash值发生改变时触发的
        // 历史回退
        window.onhashchange=function(){
     
     
            var hash=window.location.hash;
            if(hash){
     
     
                var url=hash.substring(1)
                renderView(url);
            }else{
     
     
                window.location.hash="/";
            }
        }

        function renderView(url){
     
     
            for(var i=0;i<routes.length;i++){
     
     
                if(routes[i]["path"]==url){
     
     
                    view.innerHTML=routes[i]["component"];
                    window.location.hash=url;
                }
            }
        }
    </script>
</body>
</html>

3 history模式(复杂一些)

主要使用:window.location.pathname 、history.pushState() 和 onpopstate() 来实现的
实现的代码如下:同样需要在Apach服务下运行,具体的可以评论问我!
这里需要注意的是:要想使用history模式,必须在后端配置一个文件 配置说明:https://router.vuejs.org/zh/guide/essentials/history-mode.html 文件名取为 .htaccess

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>hash</title>
</head>
<body>
    <button class="router" to="/home">首页</button>
    <button class="router" to="/content">内容</button>
    <div class="router-view">

    </div>

    <script>
        // history 模式  pushState + onpopState事件
        // 要想使用history模式,必须在后端配置一个文件  配置说明:https://router.vuejs.org/zh/guide/essentials/history-mode.html
        // 文件名取为   .htaccess
        var btn=document.getElementsByClassName("router");
        var view=document.getElementsByClassName("router-view")[0];

        routes=[
            {
     
     "path":"/home", "component":"<p>我是首页的组件</p>"},
            {
     
     "path":"/content", "component":"<p>我是内容的组件</p>"}
        ]

        // 输入路径,对应的匹配
        var url=window.location.pathname.substring(4);
        renderView(url);

        // 点击时
        for(var i=0;i<btn.length;i++){
     
     
            btn[i].onclick=function(){
     
     
                var url=this.getAttribute("to");
                renderView(url);
            }
        }

        // 历史回退  监听历史管理发生改变
        window.onpopstate=function(ev){
     
     
            view.innerHTML=ev.state;
        }

       function renderView(url){
     
     
            if(url){
     
     
                for(var i=0;i<routes.length;i++){
     
     
                    if(routes[i]["path"]==url){
     
     
                        view.innerHTML=routes[i]["component"];
                        // window.location.pathname="/Day"+url;  //我一开始想看能不能直接设置,结果发现不能
                        // 因为改变window.location.pathname会导致页面再次刷新,那也这就死循环了
                        // 所以要想其他的办法来改变url

                        // 所以就出现了history.pushState()
                        // 第一个参数:存储进历史管理的数据
                        // 第二个参数:历史管理的title(还没实现,但需要占位)
                        // 第三个参数: 路由的地址
                        history.pushState(routes[i]["component"],"",url);
                        //这就实现了
                    }
                }
            }
       }
    </script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_41800366/article/details/101055105