Fork me on GitHub

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

Coding Poineer

单页面应用hash、history原理以及JSONP的分析

单页面应用核心:不通过后端完成路由切换
(Vue、React路由切换原理类似)

history模式基于window.history/history(this===window,不写window直接可以访问),原本只有back()、go()、forward()API,在HTML5中新增pushStatereplaceState({new State},titlexxx,url)(这里的state可以在history中拿到,类似传参)

优点:
  • 即使相同的url也会被推进浏览历史栈中
  • state可以传obj类型数据作为参数,而hash只能传#短字符串
  • 还有个title可以等待使用
缺点
  • 需要后端配置支持,每一种路由需要后端有相应的接收处理,不能仅仅是最外层的url
    • 一般是通配符+返回主页面文件(此做法原因:每一次都返回打包好的index.html文件,由前端去根据state参数具体展示)
      没次go、bach、replace会触发popState方法`

hash模式基于location.href+location.hash完成,由#开头的字符串组成区分不同的hash字符串

优点
  • #及以后的值不会传给后端,而history会
  • 由上可知,hash模式不需要左后端配置
缺点
  • 不美观
    home.html文件
<body>
    <div>
        <button id='btn1'>按钮1</button>
        <button id="btn2">按钮2</button>
    </div>
</body>
<script>
    const bindEventListener = function (type) {
        const historyEvent = history[type];
        return function () {
            const newEvent = historyEvent.apply(this, arguments);
            const e = new Event(type);
            e.arguments = arguments;
            window.dispatchEvent(e);
            return newEvent;
        };
    };
    history.pushState = bindEventListener('pushState');
    history.replaceState = bindEventListener('replaceState');
    window.addEventListener('replaceState', function (e) {
        console.log('THEY DID IT AGAIN! replaceState');
    });
    window.addEventListener('pushState', function (e) {
        console.log('THEY DID IT AGAIN! pushState');
    });

    document.addEventListener('popstate', (e) => {
        console.log(e, 'popstate');
    })
    document.addEventListener('hashchange', (e) => {
        console.log(e, 'hashchange');
    })
    let btn1 = document.getElementById('btn1')
    let btn2 = document.getElementById('btn2')
    btn1.addEventListener('click', (e) => {
    })
</script>

index.html文件

<body>
    <div id='root'>
        测试
    </div>
</body>
<script>
    function callBack(data){
        var box = document.createElement('div')
        box.innerText = '回来了'
        root.appendChild(box)
    }
    function genScript(url){
        var newS = document.createElement('script');
        newS.src = url
        window.onload = function(){
            root.appendChild(newS)
        }
    }
</script>
<script>
    var root = document.getElementById('root')
    genScript('http://localhost:8080/test?cb=callback')
</script>

app.js文件

const http = require('http')
const fs = require('fs')
const httpPort = 8080

http.createServer((req, res) => {
  fs.readFile('home.html', 'utf-8', (err, content) => {
    console.log(req.url);
    if (err) {
      console.log('We cannot open "index.html" file.')
    }
    console.log('接收到');
    res.writeHead(200, {
      'Content-Type': 'text/html; charset=utf-8'
    })

    res.end()
  })
}).listen(httpPort, () => {
  console.log('Server listening on: http://localhost:%s', httpPort)
})

https://juejin.cn/post/6844903552519766029

posted @ 2021-07-23 21:59  365/24/60  阅读(140)  评论(0编辑  收藏  举报