前端路由的实现原理

发布于:2024-04-23 ⋅ 阅读:(29) ⋅ 点赞:(0)

当谈到前端路由时,指的是在前端应用中管理页面导航和URL的机制。前端路由使得单页应用(Single-Page Application,SPA)能够在用户与应用交互时动态地加载不同的视图,而无需每次都重新加载整个页面。

在前端开发中,常用的前端路由库有很多,比如React Router、Vue Router和Angular Router等。这些库提供了一组API和组件,用于定义路由规则、处理导航事件和渲染相应的视图。

简单了解前端路由后,那么前端路由实现的原理是什么呢?

浏览器的url变了需要映射到页面的某个组件,url变了需要展示某个组件。/home和Home.vue,/about和About.vue就是一一映射的关系。这个时候你就想起来router中index.js文件中,一个path对应一个component,也就是一个路径对应一个组件

1、实现路由需要解决的问题

  • 1.如何修改url还不引起页面的刷新
  • 2.如何知道url变化了

若是能解决这两个问题就可以实现前端路由了。

2、哈希Hash 路由

哈希是一种值,按照某种规则生成的一串值,用来代表一个唯一的文件,文件名后加一个哈希值,可以看到文件是否被修改过。

在浏览器中也有hash这个概念,url中接一个#,#后的值就是哈希值,按道理url变了,页面一定会刷新,但是哈希是个特例,放个哈希值就是不会刷新页面,这样,我们就解决了第一个问题,修改url不引起页面的刷新

哈希路由实现原理,上代码

<body>
    <!-- 模拟单页页面应用 -->
    <ul>
        <li><a href="#/home">首页</a></li> 
        <li><a href="#/about">关于</a></li>
        <!-- 判断url的变化,绑定点击事件不好,页面过多就很累赘,有个hashchange的官方方法 -->
    </ul>

    <div id="routeView">
        <!-- 放一个代码片段 点击首页首页代码片段生效,反之关于生效-->

    </div>
    <script>
        const routes = [
            {
                path: '#/home',
                component: '首  容'
            },
            {
                path: '#/about',
                component: '关于页面内容'
            }
        ]
        
        const routeView = document.getElementById('routeView')
        window.addEventListener('DOMContentLoaded', onHashChange) // 与vue的声明周期一个道理,dom一加载完毕就触发
        window.addEventListener('hashchange', onHashChange)
        
        function onHashChange() {
            console.log(location) // url详情,里面就有个hash值  liveserver可以帮你把html跑成服务器
            routes.forEach((item, index) => {
                if(item.path === location.hash) {
                    routeView.innerHTML = item.component
                }
            })
        }
    </script>
</body>

3、history 路由

history 路由 实现原理,上代码

<body>
    <ul>
        <li><a href="/home">首页</a></li> 
        <li><a href="/about">关于</a></li>
    </ul>

    <div id="routeView">

    </div>

    <script>
        const routes = [
            {
                path: '/home',
                component: '首页内容'
            },
            {
                path: '/about',
                component: '<h1>关于页面内容</h1>'
            }
        ]
        
        const routeView = document.getElementById('routeView')

        window.addEventListener('DOMContentLoaded', onLoad)
        window.addEventListener('popstate', onPopState)

        function onLoad() {
            const links = document.querySelectorAll('li a') // 获取所有的li下的a标签
            // console.log(links)
            links.forEach((a) => {
                // 禁用a标签的默认跳转行为
                a.addEventListener('click', (e) => {
                    console.log(e)
                    e.preventDefault() // 阻止a的跳转行为
                    history.pushState(null, '', a.getAttribute('href')) // 核心方法  a.getAttribute('href')获取a标签下的href属性
                    // 映射对应的dom
                    onPopState()
                })
            })
        }

        function onPopState() {
            console.log(location.pathname)
            routes.forEach((item) => {
                if(item.path === location.pathname) {
                    routeView.innerHTML = item.component
                }
            })
        }
    </script>
</body>