spa单页面开发的尝试

首先 spa是什么

单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML
页面并在用户与应用程序交互时动态更新该页面的Web应用程序。

提取要点来理解 单个html文件,动态更新。直观的说就是没有后续的页面加载处理,(不会再任何位置重新加载,也不会去申请其他页面资源)

那么为什么要用这个技术
可以先看看网易云音乐官网的处理。(大部分的首页处理并非全部)。在使用的时候我们明显体会到了跟多页面的不同。在用户体验上的优势是这个技术得以流行的主要原因。列举如下:

  • 快速渲染和及时反馈
  • 响应时间缩短,在传统网站中,对于用户的请求 会有一个 请求-反应-重绘的周期,处理时间更长,但是在单页应用中,更多的处理逻辑将在前端执行,服务端的工作只有必要的数据验证,数据持久存储等,以加快响应时间
  • 避免资源浪费。在网易云音乐的官网中,用很大一部分是固定资源(比如标题 边框等等)占据很多空间。但是如果做成多页面的话,将会浪费时间去做反复的整张重绘
  • 可以控制的加载过程展示,相对于传统网站,可以在加载的过程中给出更加友好的过程展示

应该怎么做
两种方法:hash 和 history
hash:

hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)

#代表的不是路径的一部分 而是一个代表位置的字符,还记得学习HTML时有说过a标签一开始是用来定位的。a标签的确可以实现锚点,还有一种方法,(看着#可能会想到是不是跟id有关。)id属性 也可以实现。
需要强调几点

  1. http请求不包括#以及之后的部分
  2. 改变hash(#)会改变浏览器的浏览历史记录
  3. 改变hash(#)不会导致页面重载

从别人的例子我们知道,要实现的无非自己来决定是#之后的内容,以及动态更新前端资源(ajax)
核心代码是

window.addEventListener('hashchange',function(){
            var hash = document.location.hash;
            ...
            ...
            ...
}

以下是我实现的的效果图spa单页面开发的尝试

这里是代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .one,.two{
            width: 1000px;
            height: 300px;
            border: 1px solid black;
            margin: 0 auto;
        }
        #daixuan{
            height: 50px;
            width: 100%;
            background-color: antiquewhite
        }
    </style>
</head>
<body>
    <div id="daixuan">
            <a href="#first">the first one</a> <a href="#second">the second one</a>
    </div>
    <div id="first">
       
        <div class="one"></div>
        <div class="two"></div>
    </div>
    <script>
        window.addEventListener('hashchange',function(){
            var hash = document.location.hash;
            if(hash == '#first'){
            
                var xhr = new XMLHttpRequest();
                xhr.onload = function(){
                    var output =  JSON.parse(xhr.responseText);
               console.log(output);
                document.getElementsByClassName('one')[0].innerHTML = output[0] .say;
                document.getElementsByClassName('two')[0].innerHTML = output[0].reply;
                }
                xhr.open('GET','./data.json',true);
                xhr.send();
            }
            if(hash == '#second'){
             
                var xhr = new XMLHttpRequest();
                xhr.onload = function(){
                    var output =  JSON.parse(xhr.responseText);
               console.log(output);
                document.getElementsByClassName('one')[0].innerHTML = output[1] .say;
                document.getElementsByClassName('two')[0].innerHTML = output[1].reply; 
                }
                xhr.open('GET','./data.json',true);
                xhr.send();
            }
        })
    </script>
</body>
</html>

待传的json数据在这里

[
    {
        "say":"This is the first one",
        "reply":"Hello,the first one"
    },
    {
        "say":"This is the second one",
        "reply":"Hello,the second one"
    }
]

细节就不多说了,欢迎指正。但是要强调:Chrome浏览器不接受file协议,即本地json数据,使用时会报错,像这样:
spa单页面开发的尝试
我的处理方式是在vscode里下载live server插件。

另一种方式是通过html5
的history api:
history.pushState()和history.replaceState(),一个事件history.onpopstate.

  • [ history.pushState(stateObj, title, url)
    stateObj为一个状态对象,这个对象可以被popstate事件读取,也可以在history对象中获取。
    title为标题一般使用空串来代替。
    url为路径。 pushState是向浏览器的历史记录栈中压入一个历史记录。]

  • [history.replaceState()所接受的参数相同,作用为代替记录。

onpopstate事件  在点击浏览器浏览记录前进后退时触发

这个方法我只做了初步了解,在实现之后我再把代码和样例附上。