首先 spa是什么
单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML
页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
提取要点来理解 单个html文件,动态更新。直观的说就是没有后续的页面加载处理,(不会再任何位置重新加载,也不会去申请其他页面资源)
那么为什么要用这个技术
可以先看看网易云音乐官网的处理。(大部分的首页处理并非全部)。在使用的时候我们明显体会到了跟多页面的不同。在用户体验上的优势是这个技术得以流行的主要原因。列举如下:
- 快速渲染和及时反馈
- 响应时间缩短,在传统网站中,对于用户的请求 会有一个 请求-反应-重绘的周期,处理时间更长,但是在单页应用中,更多的处理逻辑将在前端执行,服务端的工作只有必要的数据验证,数据持久存储等,以加快响应时间
- 避免资源浪费。在网易云音乐的官网中,用很大一部分是固定资源(比如标题 边框等等)占据很多空间。但是如果做成多页面的话,将会浪费时间去做反复的整张重绘
- 可以控制的加载过程展示,相对于传统网站,可以在加载的过程中给出更加友好的过程展示
应该怎么做
两种方法:hash 和 history
hash:
hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)
#代表的不是路径的一部分 而是一个代表位置的字符,还记得学习HTML时有说过a标签一开始是用来定位的。a标签的确可以实现锚点,还有一种方法,(看着#可能会想到是不是跟id有关。)id属性 也可以实现。
需要强调几点
- http请求不包括#以及之后的部分
- 改变hash(#)会改变浏览器的浏览历史记录
- 改变hash(#)不会导致页面重载
从别人的例子我们知道,要实现的无非自己来决定是#之后的内容,以及动态更新前端资源(ajax)
核心代码是
window.addEventListener('hashchange',function(){
var hash = document.location.hash;
...
...
...
}
以下是我实现的的效果图
这里是代码:
<!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数据,使用时会报错,像这样:
我的处理方式是在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事件 在点击浏览器浏览记录前进后退时触发
这个方法我只做了初步了解,在实现之后我再把代码和样例附上。