SPA单页应用设计原理

319 阅读3分钟

1.设计意义

  • 前后端分离
  • 减少服务器的压力
  • 增强用户的体验
  • 预渲染的SEO
  1. 前后端分离: 前端做业务逻辑,后端处理数据和接口,耦合度减少,开发效率提高
  2. 减少服务器的压力: 1个页面不用每次都去请服务端,当1个应用较复杂,有10多个页面的时候,那么每个用户操作几个页面,只需要请求1次,这会在很大程度上减轻服务器压力。
  3. 增加用户体验: 如当从1个首页跳转详情页,如果按照传统页面的方式,相当于在首页请求,在去服务端请求另1个详情页,每1次的连接,都要消耗DNS以及TCP建立连接再加上页面传输的过程还要包括接口响应的时间,这个都是用户可以感受的到的,那么当使用单页面的时候,不存在多次下载页面的时间,只有接口消耗的时间,这在很大程度上增强了用户体验
  4. 预渲染的SEO: SPA对SEO不太友好

2.工作原理

-- 实现方面的主要有两大类History API和Hash实现,那么这两种之间有什么区别呢?

第一个History API更加优雅,但是对浏览器是有一定要求的,第二个Hash看上去不是特别的优雅,但是它是兼容性最好的方案。

  1. History API

如上图,左边对应的入口一,二,三,对应页面上的页面一,二,三的,一个入口点进去,应该对应一个页面,这个是入口的作用。那么它们之间是怎么关联上的?比如我点击了入口二,怎么让页面二打开,记住这里的页面二打开是不要请求服务端,是通过本地的JS控制,第是第一步。 第二个是点击浏览器的前进后退或者是其它控制,它怎么回到某个入口对应的页面上去,这是第二步。 以上二步就是SAP要控制的动作,如上图中间部分 History对象,就是实现的一个中间桥梁,History对象下的两个小东西onpopstate和pushState,这是来实现这两步的。

. onpopstate : 记录响应浏览器的前进和后退

. pushState: 创建一个历史

    <a class="api a">a.html</a>
    <a class="api b">b.html</a>
    <script>
        // 注册路由
        document.querySelectorAll('.api').forEach(item => {
            item.addEventListener('click', e => {
                e.preventDefault();
                let link = item.textContent;
                window.history.pushState({name: 'api'}, link, link);
            }, false)
        });
        // 监听路由
        window.addEventListener('popstate', e => {
            console.log({
                location: location.href,
                state: e.state
            });
        }, false)
    </script>

说明 :代码中主要有两个a标签,a.html,b.html,js注册a标签点击事件,通过history.pushState创建一个历史记录进行页面切换,pushState主要有三个参数,第一个就是传送参数,第二个是页面的标题,第三个就是跳转URL。 然后通过监听onpopstate,就可以知道浏览器前进和回退一些信息。

如上,当我点击a.hmtl地址栏的就发生变化,页面切到了a.html,但页面不会刷新,同理点击b.html效果也是一新。

当我们点击回退的时候,就会显示具体信息了。

  1. Hash

其实hash与History流程差不多,不同的是,桥梁发生了变化。大家知道,一个URL上有post,path,search还有hash。那么hash是怎么做的呢?

当我们改变一个地址的时候,去修改hash,然后监听hashchange事件,你就知道页面的地址发生的变化,然后在这个事件里面去做相应的动作,就能完成刚才所说的这种页面的切换。

演示图