前端hash路由和H5-history路由的实现原理,及区别

1,549 阅读1分钟

hash路由

    <div>
        <button id="btn">跳转</button>
    </div>

    <script>
        const btn = document.querySelector('#btn')

        /* 监听hash的值变法 */
        window.onhashchange = (event) => {
            /* 当浏览器前进后退也会触发hash的变法 */
            const newURL = event.newURL
            const oldURL = event.oldURL
            console.log('event', event)
            console.log('newURL', newURL)
            console.log('oldURL', oldURL)
        }

        btn.addEventListener('click', (event) => {
            window.location.href = '#/user'
        })
    </script>

H5-history

    <div>
        <button id="btn">跳转</button>
        <button id="goBack">返回</button>
    </div>

    <script>
        const btn = document.querySelector('#btn')
        const goBack = document.querySelector('#goBack')

        goBack.addEventListener('click', (event) => {
            history.back()
        })

       
        btn.addEventListener('click', (event) => {
            const state = {name: 'home'}
            // 第二个参数没用,只是留着,以后做扩展
            window.history.pushState(state, '', 'page1')
        })

        /* 浏览器前进后退触发 */
        window.onpopstate = (event) => {
            const stete = event.state //获取跳转的时候传递过来的state,只有在state有的时候
            //,才返回有的值
            // 改变的时候,显示当前页面的state
            console.log('前进后退', event)
        }

        // 这个需要服务端支持,不管前端访问什么路由;
        // 服务端都返回默认的index.html给前端,前端自己处理路由的变化

        // onpopstate 和 onhashchange的区别
        // onpopstate 是在浏览器前进后退的时候触发        
        // onhashchange 是在hash改变的时候触发,一般来说,onhashchange触发的条件广一些
    </script>

总结

从某种程度来说, 调用 pushState() 和 window.location = "#foo"基本上一样, 他们都会在当前的document中创建和激活一个新的历史记录。但是 pushState() 有以下优势:

  • 新的URL可以是任何和当前URL同源的URL。但是设置 window.location 只会在你只设置锚的时候才会使当前的URL。
  • 非强制修改URL。相反,设置 window.location = "#foo"; 仅仅会在锚的值不是#foo情况下创建一条新的历史记录。
  • 可以在新的历史记录中关联任何数据。window.location = "#foo"形式的操作,你只可以将所需数据写入锚的字符串中。