tip
SPA
的学习记录,可能不太严谨, 欢迎大佬指正。
什么是SPA
SPA
是 single page web application
的缩写,即单页Web应用,就是只有一张Web页面的应用,是加载单个HTML
页面并在用户与应用程序交互时动态更新该页面的Web应用程序。浏览器一开始会加载必需的HTML、CSS和JavaScript
,所有的操作都在这张页面上完成,都由JavaScript
来控制,通过JavaScript
动态控制页面中显示的内容,从而模拟出多个页面的效果。
SPA在现在非常常见,当前流行的Vue
、React
等许多框架都使用了SPA
。最直观的感受就是,当你在当前页面触发了某个跳转使当前的网页URL改变了,但是你依然停留在当前页面,并没有打开新窗口或者刷新到新页面。
SPA的原理
简单来说,就是通过JS
监听到URL
的变化,从而对页面进行处理。
History
模式下
Hash
模式下
SPA的实现
要实现SPA,需要前端路由来监听页面URL的变化从而对页面有所响应。前端路由有两种模式:hash 模式和 history 模式。接下来先说说这两种模式的实现方法。
History模式
起步
首先,我们要知道什么情况下会导致页面刷新,举个例子:
https://www.bing.com/ //初始状态
https://www.bing.com/test //URL改变,页面刷新,显示目标页面
我们要实现的效果是:
https://www.bing.com/ //初始状态
https://www.bing.com/test //URL改变,页面不刷新,显示目标页面
要实现这个功能,我们要用到浏览器中的几个API。
首先我们在浏览器中打印一下 window
对象,结果为:
打开history
我们发现:
这就是实现SPA
的核心了,接下来简单介绍一下这几个方法。
核心API介绍
pushState()
pushState()
需要三个参数: 一个状态对象, 一个标题 (目前被忽略), 和 (可选的) 一个URL.
举个例子你就能轻松理解它的作用
在浏览器中打开 https://www.bing.com/
并打开控制台
在控制台中输入 history.pushState({name:"test"}, "page B", "pageB.html");
我们就会发现浏览器的URL发生了改变,但是页面并没有刷新。
我们继续点击后退试试
看到这里,你应该很清楚 pushState()
的作用了
replaceState()
replaceState()
的效果大致和pushState()
差不多,不过replaceState()
是替换当前URL,pushState()
是在当前URL后追加。
back(),forward(),go()
window.history.back()
----------> 在history中向后跳转,相当于点击了浏览器的后退按钮。window.history.forward()
-------> 在history中向前跳转,相当于点击了浏览器的前进按钮。window.history.go()
-------------> 跳转历史中的某一特定页面, 通过与当前页面相对位置来标志 (当前页面的相对位置标志为0)。例如window.history.go(-1)
相当于点击了浏览器的后退按钮。
popstate事件
每当活动的历史记录项发生变化时, popstate
事件都会被传递给window对象。如果当前活动的历史记录项是被 pushState
创建的,或者是由 replaceState
改变的,那么 popstate
事件的状态属性 state
会包含一个当前历史记录状态对象的拷贝。
这里需要注意的是,调用history.pushState()
或者history.replaceState()
不会触发popstate事件. popstate
事件只会在浏览器某些行为下触发, 比如点击后退、前进按钮(或者在JavaScript中调用history.back()、history.forward()、history.go()
方法),此外,a 标签的锚点也会触发该事件。
当网页加载时,各浏览器对popstate
事件是否触发有不同的表现,Chrome 和 Safari会触发popstate
事件, 而Firefox不会。
举个例子
当我们点击该元素时,页面的URL
便会发生改变,且并不会引起页面刷新
如上文所说,pushState()
并不会触发popstate
事件,而前进后退均触发了popstate
事件
其实到这里我们就已经实现了前端跳转,页面不刷新,只需配合使用JS控制自己想要展示的内容即可。
Hash模式
起步
同样的,我们首先要知道在Hash
模式下,什么情况会导致浏览器跳转刷新。
https://www.bing.com/# //初始状态
https://www.bing.com/#/test //URL改变,页面不刷新
https://www.bing.com/# //初始状态
https://www.bing.com/test/#/test //URL改变,页面刷新
由此可知,hash
模式下当井号 #
后面的路径发生变化时,浏览器并不会重新发起请求,而是触发hashchange
事件。同样的,我们只需要监听到路径的变化即可。
首先打印一下window
对象
打开location
我们发现
和history
模式下的操作类似,我们在改变location.hsah
时,监听到hash
的改变,从而进行处理即可。
举个例子
我们在原来的基础上添加一个按钮并为其绑定点击事件,使其被点击时改变当前页面URL
当我们改变hash
时,会同时触发popstate
事件和hashchange
事件。
到这里,我们已经监听到hash
的变化,只需在URL改变时实现需要的功能即可。
总结
其实简单的说,实现SPA就是在不刷新页面不打开新页面的情况下实现不同数据的展示,而我们要实现这个功能,只需要知道什么情况下浏览器不会刷新页面,怎么改变URL
使浏览器只发生前端跳转而不刷新页面,然后我们在这个基础上监听到URL
的改变,做对应的处理就好了。