美文网首页前端框架实现原理
原生js实现框架路由方式

原生js实现框架路由方式

作者: 谢炳南 | 来源:发表于2019-05-18 11:08 被阅读0次

目前来说,无论是vue,还是react,spa的路由实现方式无非就是以下两者

1.hash方式。 使用location.hash和hashchange事件实现路由
2.history api。使用html5的history api实现,主要就是popState事件等。

hash用的还是比较多的,但是这种方式的url会比较丑陋,会出现 #; 而history api就可以很好的解决这个问题,但是需要后端配置,并且由于是html5中的api,所以兼容性还不是很好

路由实现之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>
            // 创建Router构造函数
            // currentHash为当前hash值,routes为路径对象
            function Router() {
                this.currentHash = '/';
                this.routes = {};
            }

            // 注册路径,每个路径对应一个回调函数。 
            Router.prototype.route = function(path, callback) {
                this.routes[path] = callback || function() {
                    alert('未定义回调函数!');
                }
            }

            // 更新页面函数
            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>

路由实现之history API

html5中的history api包括两个方法history.pushState()和history.replaceState(),包含一个事件history.onpopstate。参考MDN
1044137-20170824080502933-232401939.png
注意:因为pushState的url和当前的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>
            // 创建Router构造函数
            function Router() {
                this.currentRoute = '';
                this.routes = {};
                this.init();
            }

            // 注册路由函数
            Router.prototype.route = function(path, callback) {

                // 根据type类型,选择相应的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;

                // 重新加载函数,这里使用的主机是http://localhost:8088/
                window.addEventListener('load', function() {
                    self.currentRoute = location.href.slice(location.href.indexOf('/', 8));
                    console.log(self.currentRoute);
                    self.refresh(self.currentRoute);
                });

                // 当用户点击前进后退按钮时触发函数
                window.addEventListener('popstate', function() {
                    console.log('history.state.path:', history.state.path);
                    self.currentRoute = history.state.path;
                    self.refresh(self.currentRoute, 2);
                }, false);

                // 对所有的link标签进行绑定事件
                var historyLinks = document.querySelectorAll('.history-link');
                for(var i = 0, len = historyLinks.length; i < len; i++) {
                    historyLinks[i].onclick = function(e) {
                        // 阻止默认
                        e.preventDefault();
                        self.currentRoute = e.target.getAttribute('href');
                        self.refresh(self.currentRoute, 1);
                    }
                }
            }
        </script>

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

            // 实例化Router
            window.Router = new Router();

            // 注册路由,实现相应功能

            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>

相关文章

网友评论

    本文标题:原生js实现框架路由方式

    本文链接:https://www.haomeiwen.com/subject/jowzaqtx.html