原生js實(shí)現(xiàn)框架路由方式

目前來說,無論是vue,還是react,spa的路由實(shí)現(xiàn)方式無非就是以下兩者

1.hash方式。 使用location.hash和hashchange事件實(shí)現(xiàn)路由
2.history api。使用html5的history api實(shí)現(xiàn),主要就是popState事件等。

hash用的還是比較多的,但是這種方式的url會比較丑陋,會出現(xiàn) #; 而history api就可以很好的解決這個問題,但是需要后端配置,并且由于是html5中的api,所以兼容性還不是很好

路由實(shí)現(xiàn)之hash

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>router</title>
        <style>
            html,
            body {
                width: 100%;
                height: 100%;
                margin: 0;
            }
            
            div.router-wrap {
                width: 100%;
                height: 100%;
                background: #fefefe;
            }
            
            a {
                padding: 10px;
                color: pink;
                font-size: 25px;
                font-weight: bold;
                text-decoration: none;
            }
        </style>
    </head>

    <body>
        <div class="router-wrap">
            <a href="#/black">黑色</a><br>
            <a href="#/green">綠色</a><br>
            <a href="#/red">紅色</a>
        </div>
        <script>
            // 創(chuàng)建Router構(gòu)造函數(shù)
            // currentHash為當(dāng)前hash值,routes為路徑對象
            function Router() {
                this.currentHash = '/';
                this.routes = {};
            }

            // 注冊路徑,每個路徑對應(yīng)一個回調(diào)函數(shù)。 
            Router.prototype.route = function(path, callback) {
                this.routes[path] = callback || function() {
                    alert('未定義回調(diào)函數(shù)!');
                }
            }

            // 更新頁面函數(shù)
            Router.prototype.refresh = function() {
                this.currentHash = location.hash.slice(1) || '/';
                this.routes[this.currentHash]();
            }

            // 初始化
            Router.prototype.init = function() {
                var self = this;
                window.addEventListener('load', function() {
                    self.refresh();
                }, false);

                window.addEventListener('hashchange', function() {
                    self.refresh();
                });
            }
        </script>

        <script>
            var wrap = document.querySelector('.router-wrap');

            window.Router = new Router();
            Router.route('/', function() {
                wrap.style.backgroundColor = '#fefefe';
            });

            Router.route('/black', function() {
                wrap.style.backgroundColor = 'black';
            });

            Router.route('/green', function() {
                wrap.style.backgroundColor = 'green';
            });

            Router.route('/red', function() {
                wrap.style.backgroundColor = 'red';
            });

            Router.init();
        </script>
    </body>

</html>

路由實(shí)現(xiàn)之history API

html5中的history api包括兩個方法history.pushState()和history.replaceState(),包含一個事件history.onpopstate。參考MDN

1044137-20170824080502933-232401939.png

注意:因?yàn)閜ushState的url和當(dāng)前的Url必須是同源的,而file://的形式是不存在同源的說法的,所以我們必須用http://localhost的方式。

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>router</title>
        <style>
            html,
            body {
                width: 100%;
                height: 100%;
                margin: 0;
            }
            
            div.router-wrap {
                width: 100%;
                height: 100%;
                background: #efefef;
            }
            
            a {
                display: inline-block;
                padding: 10px;
                color: pink;
                font-size: 25px;
                font-weight: bold;
                text-decoration: none;
            }
        </style>
    </head>

    <body>
        <div class="router-wrap">
            <a href="/black" class="history-link">黑色</a><br>
            <a href="/green" class="history-link">綠色</a><br>
            <a href="/red" class="history-link">紅色</a>
        </div>

        <script>
            // 創(chuàng)建Router構(gòu)造函數(shù)
            function Router() {
                this.currentRoute = '';
                this.routes = {};
                this.init();
            }

            // 注冊路由函數(shù)
            Router.prototype.route = function(path, callback) {

                // 根據(jù)type類型,選擇相應(yīng)的history api。  
                this.routes[path] = function(type) {
                    if(type == 1) {
                        history.pushState({
                            path: path
                        }, '', path);
                    } else if(type == 2) {
                        history.replaceState({
                            path: path
                        }, '', path);
                    }
                    callback();
                }
            }

            // 更新頁面
            Router.prototype.refresh = function(path, type) {
                this.routes[path](type);
            }

            // 初始化
            Router.prototype.init = function() {

                var self = this;

                // 重新加載函數(shù),這里使用的主機(jī)是http://localhost:8088/
                window.addEventListener('load', function() {
                    self.currentRoute = location.href.slice(location.href.indexOf('/', 8));
                    console.log(self.currentRoute);
                    self.refresh(self.currentRoute);
                });

                // 當(dāng)用戶點(diǎn)擊前進(jìn)后退按鈕時(shí)觸發(fā)函數(shù)
                window.addEventListener('popstate', function() {
                    console.log('history.state.path:', history.state.path);
                    self.currentRoute = history.state.path;
                    self.refresh(self.currentRoute, 2);
                }, false);

                // 對所有的link標(biāo)簽進(jìn)行綁定事件
                var historyLinks = document.querySelectorAll('.history-link');
                for(var i = 0, len = historyLinks.length; i < len; i++) {
                    historyLinks[i].onclick = function(e) {
                        // 阻止默認(rèn)
                        e.preventDefault();
                        self.currentRoute = e.target.getAttribute('href');
                        self.refresh(self.currentRoute, 1);
                    }
                }
            }
        </script>

        <script>
            var wrap = document.querySelector('.router-wrap');

            // 實(shí)例化Router
            window.Router = new Router();

            // 注冊路由,實(shí)現(xiàn)相應(yīng)功能

            Router.route('/', function() {
                wrap.style.backgroundColor = '#efefef'
            });

            Router.route('/black', function() {
                wrap.style.backgroundColor = 'black';
            });

            Router.route('/green', function() {
                wrap.style.backgroundColor = 'green';
            });

            Router.route('/red', function() {
                wrap.style.backgroundColor = 'red';
            });
        </script>
    </body>

</html>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容