Router路由的实现

505 阅读1分钟

来由

前端路由的诞生的缘由前端路由的出现要从 ajax 开始,Ajax全称 Asynchronous JavaScript And XML,是浏览器用来实现异步加载的一种技术方案。用以名言来说:世界上本没有前端路由,需求的人多了,也就出现了前端路由这个名词。

什么是前端路由

路由的概念是服务器上,URL和处理函数的映射关系。 前端路由在单页应用中体现,描述的是 URL 和 UI 页面的映射关系,即 URL 变了引起 UI 更新( 无需刷新页面 )

如何实现

  1. 如何改变 URL 却不引起页面的刷新?
  2. 如何检测到 URL 变化?

实现方法

Hash实现

  • hash 实现:hash 是 URL 后面的那一部分,改变 URL 中的 hash,页面不刷新
  • hashchange ( 原生js自带 )
<body>
    <ul>
        <li><a href="#/home">home</a></li>
        <li><a href="#/about">about</a></li>
    </ul>

    <div id="routerView"></div>

    <script>
        var routerView = document.getElementById('routerView')
        window.addEventListener('DOMContentLoaded',onHashChange)
        
        // 监听 url 的变化
        window.addEventListener('hashchange', onHashChange)

        function onHashChange() {
            console.log(location);
            switch (location.hash) {
                case '#/home':
                    routerView.innerHTML = 'Home Page'
                    break;
                case '#/about':
                    routerView.innerHTML = 'About Page'
                    break;
                default:
                    return
            }
        }
    </script>
</body>

history 实现

  • history 实现: 是 HTML 提供的一个对象,其中提供了 pushState 和 replaceState 两个方法,这两个方法都可以改变 URL 且不引起页面刷新
  • popState 可以监听 由 pushState 和 replaceState 改变的URL
  • pushState 和 replaceState 的调用和 a 标签的点击事件 是可以被拦截的
<body>
    <ul>
        <li><a class="link1" href="/home">home</a></li>
        <li><a class="link2" href="/about">about</a></li>
    </ul>

    <div id="routerView"></div>

    <script>
        //  只要是用 pushState 或 replaceState 让url变化的,就能用popState监听到
        window.addEventListener('popstate',onLoad)
        

        function onPopState() {
            // console.log(location.pathname);
            switch (location.pathname) {
                case '/home':
                    routerView.innerHTML = '<h2>HOME page</h2>'
                    break;
                case '/about':
                    routerView.innerHTML = '<h2>ABOUT page</h2>'
                    break;  
                default:
                    break;
            }

        }
        

        function onLoad() {
                var routerView = document.getElementById('routerView')
                onPopState()

                // 拦截a标签的点击事件
                var linkList = document.querySelectorAll('ul li a')
                // console.log(linkList);
                linkList.forEach(el => {
                    el.addEventListener('click', function(e) {
                        e.preventDefault()  //阻止a标签默认的跳转事件
                        console.log(e);
                        history.pushState(null, '', el.getAttribute('href'))  //核心步骤,修改了url页面未刷新
                        onPopState()
                    })
                })
            }

        window.addEventListener('DOMContentLoaded', onLoad)
    </script>
</body>

总结

以上两种方法就是前端路由的实现,在学习初期对于这些概念性的理解还是蛮重要的,如果哪里说的的不好的欢迎大佬指正,求赞求支持!