一直对spa充满好奇到底怎么实现 ,刚好今天看面经看到了这题,下面是我看到的觉得蛮好的,就转了。
1、单页面应用(SPA)的概念:

1、single-page application是一种特殊的Web应用。它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript、CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转,而是利用JavaScript动态的变换HTML(采用的是div切换显示和隐藏),从而实现UI与用户的交互。
2、简单来说SPA的网页只有一个页面,而这个网页的实际方式要能够回应使用者所使用的各种装置并且赋值使用者在电脑上使用软件的体验,让使用者可以更容易和有效的使用网站。按照正常情况下,我们会在一个页面中链接到其他的很多个页面,进行页面的跳转,但是如果使用单页面应用的话,我们始终在一个页面中,通常使用a标签的描点来实现。

2、作用(好处)

1、由于避免了页面的重新加载,SPA可以提供较为流畅的用户体验。得益于Ajax,可以实现无跳转刷新,由于与浏览器的history机制,可以使用hash的b变化从而可以实现推动界面变化。
2、只要使用支持HTML5和CSS3的浏览器就可以执行复杂的SPA,因此,开发人员不必为了写SPA网站而特别学习另一个开发方式,而使用者也不额外安装软件,所以,让开发SPA网页程序的入门和使用门槛降低不少。

3、缺点

以SPA方式开发的网站不容易管理也不够安全。
因为没了一页一页的网页给搜索引擎的爬虫来爬,所以,在搜索引擎最佳化(SEO)的工作上,需要花费额外的功夫。
因为没有换页,需要自定义状态来取代传统网页程序以网址来做判断。

4、实现SPA

技术:
1、处理#后面的字符
2、局部刷新

3、iframe

1、#后面的字符

后面的字符,其实是location对象的hash属性的值,即是说,我们可以轻松拿到这个#后面字符的变化值,代码如下:

var hash = location.hash;

既然值能拿到,就可以直接通过一个a标签跳转。

<a href="#luoxuan">罗旋</a>;
<a href="#xiexing">谢星</a>;
<a href="#luoli">罗粒</a>;
<a href="#luobo">罗卜</a>;

2、局部刷新(Ajax)

ajax+div+historyapi

这种方式实现要更复杂,开发要自己实现url管理,以达到前进、后退跳转等能力,不过目前都已经有成熟的路由库可以使用,另外基于div模式的SPA,开发需要考虑全局对局部的影响,包括css、事件等。这种方式的优点是刷新要更轻量,js库和css样式在首次加载即可,局部页面可以只加载少量的数据,并且基于div响应式效果在移动端要更好。因此这也成了目前流行的前端框架angular、react等选用的方案。

代码实现:

<script>window.addEventListener('haschange',function(){var hash  = document.location.hash;switch(hash){case '#luoxuan':$.ajax({url:'./json/luoxaun.json',success:function(){document.write("罗旋是小仙女!!!")}});break;case '#xiexing':$.ajax({url:'./json/xiexing.json',success:function(){document.write("谢星是个帅哥哥哦~~~")}});break;}})
</script>

3、iframe

其一,使用iframe的优点之一就是开发简单,目前的浏览器都已经对iframe url发生修改产生历史记录。

其二,除了响应式问题的兼容性不好之外(也正因此iframe很不适合用在移动端),iframe作为使用多年的浏览器技术之一,在许多方面的兼容性要好许多,也是一些新技术在低版本浏览器上不可用时的替代解决方案,如contentEditable。

其三,iframe与父文档相对独立,可以不受父文档的影响,想必这也是目前一些网站(网易云音乐,QQ空间,各大邮箱)继续使用iframe的主要原因。

基于iframe制作单页博客
笔者的博客制作于2015年,当时的PC浏览器应该不支持iframe历史记录,所以笔者选择通过修改hash的方式实现历史记录(浏览器对hash的修改会记录历史记录),选择基于iframe制作基于两个原因:一、希望浏览博客时不论怎么跳转,可以不中断播放音乐;二、iframe相对全站ajax+div而言要更简单易行。博客地址http://movesun.com,博客布局参考 http://www.kotonohanoniwa.jp/。

做法是绑定所有需要在iframe中打开的a标签的click事件,当点击a标签时,将a标签url中的path路径修改为浏览器url的hash值。例如我想访问的是 http://movesun.com/blog/list,则将/blog/list作为hash值设置到地址栏 ,因此在浏览器地址栏看到的地址就变为了http://movesun.com/#/blog/list,

因此在父文档中有这样一段js

 1 $('a[target="contentFrame"]').click(function(){2     var $this = $(this),3         url = $this.attr('href'),4         mainHost = location.host,5         i = url.indexOf(mainHost);6     $active.removeClass('active');7     $active = $this.parent('li');8     $active.addClass('active');9     if(i !== -1){
10         url = url.substr(i + mainHost.length);
11     }
12     window.location.hash = '#' + url;
13     return false;
14 });

在iframe页面(子页面)中,也有一段类似的js,为iframe中的页面超链接绑定事件

 1 $('a').click(function(){2     var url = $(this).attr('href')3     if(url && url != '#' && url.indexOf('http') == 0){4         var mainHost = window.parent.location.host,5                 i = url.indexOf(mainHost);6         if(i !== -1){7             url = url.substr(i + mainHost.length);8         }9         window.parent.location.hash = '#' + url;
10     }
11     return false;
12 });

注意这两段代码,修改的都是父文档(顶层窗口)地址栏的hash值。所以,只需要在父文档中监听onhashchange事件,在事件响应中设置iframe的src 进而load子页面。

1 $container = $('div.page-body > iframe');
2 window.onhashchange = function(){
3     $container.attr('src',location.hash.substring(1));
4 };

iframe高度不能根据内容自适应,需要在子页面load之后刷新iframe的高度

 1 var refreshHeight = function(){2     var $this = $container,3         minHeight = $('.page-right').height() - $('.top-menu').height() - 20,4         contentHeight = $this.contents().find('body').height() + 10;5     $this.height(contentHeight < minHeight ? minHeight : contentHeight);6 };7  8 $container.load(function(){9     refreshHeight();
10 });
11 // 首次刷新,否则加载过程中会看到白框
12 refreshHeight();

到这里基本已经实现任意跳转、回退、前进页面不再刷新整个页面。下面的代码是为了解决当打开多个顶层文档时(开多个窗口),音乐不重复播放,方法也很简单,在localStorage中记录顶层文档的数量,每开一个新窗口加1,关闭时减1,只要记录数大于1便不自动播放。

 1 if(window.localStorage){2     var $window = $(window);3     $window.on('beforeunload',function(){4         console.log('-1');5         localStorage.framePage = localStorage.framePage - 1;6     });7  8     window.addEventListener("storage", function(e){9         console.log("oldValue: "+ e.oldValue + " newValue:" + e.newValue)
10     });
11 }
12 var autoplay =  location.host !== 'movesun.qq.com';
13 if(window.localStorage){
14     if(Number(localStorage.framePage) >= 1){
15         autoplay = false;
16     }
17
18     if(isNaN(localStorage.framePage) || Number(localStorage.framePage) <= 0) localStorage.framePage = 1;
19     else {
20         localStorage.framePage = Number(localStorage.framePage) + 1;
21     }
22 }

博客依然有两个问题需要解决

1、目前的浏览器已经支持记录iframe变更的历史记录,通过hash记录历史就显的没有必要了。目前网站每次跳转实际产生了两条历史记录。后面找时间移出hash记录或者禁用iframe历史记录

2、考虑到搜索引擎收录的超链接应该是非hash模式的url,比如用户看到的是movesun.com/#/blog/list ,而实际收录的却是movesun.com/blog/list,通过site:movesun.com指令搜索也可以看到

直接访问这类url地址,将直接打开iframe里的内容,所以,当用户直接点击搜索引擎的结果进入博客时,应该将用户跳转到hash模式,页面才能正常显示,但这样对搜索引擎而言,会陷入一个无限循环,影响搜索引擎收录。

总结:SPA(单页面web应用)和MPA(多页面web应用)的区别

SPA(单页面应用)总结相关推荐

  1. 通过Blazor使用C#开发SPA单页面应用程序(4) - Ant Design

    通过Blazor使用C#开发SPA单页面应用程序(1) 通过Blazor使用C#开发SPA单页面应用程序(2) 通过Blazor使用C#开发SPA单页面应用程序(3) 前面学习了Blazor的特点.环 ...

  2. [vue] SPA单页面的实现方式有哪些?

    [vue] SPA单页面的实现方式有哪些? 1.监听地址栏中hash变化驱动界面变化2.用pushsate记录浏览器的历史,驱动界面发送变化3.直接在界面用普通事件驱动界面变化它们都是遵循同一种原则: ...

  3. [vue] 说说你对SPA单页面的理解,它的优缺点分别是什么?

    [vue] 说说你对SPA单页面的理解,它的优缺点分别是什么? 介绍:SPA应用就是一个web应用,可理解为:是一种只需要将单个页面加载到服务器之中的web应用程序.当浏览器向服务器发出第一个请求时, ...

  4. SPA单页面应用首屏加载速度提升方法

    SPA单页面应用首屏加载速度提升方法 首屏加载 计算首屏加载时间公式 解决方法 减少入口文件体积 静态资源本地缓存 UI框架按需加载 避免组件重复打包 图片资源压缩 开启GZip压缩 首屏加载 首屏加 ...

  5. (25):SPA单页面的理解

    对SPA单页面的理解,它的优缺点分别是什么,如何实现SPA应用 一.什么是SPA 1.SPA(single-page application),翻译过来就是单页应用 2.SPA是一种网络应用程序或网站 ...

  6. spa单页面应用html缓存问题

    一.背景 浏览器的http请求都有一个缓存机制,简单点说就是同路径同名文件会默认被缓存下来,提升下次访问时的速度,默认只有刷新页面或长时间未访问时才会刷新缓存. 而spa单页面应用是通过路由切换来访问 ...

  7. Java快速开发平台,JEECG 3.7.5 Vue SPA单页面应用版本发布

    JEECG 3.7.5 Vue SPA单页面应用版本发布 导读            ⊙ Vue+ElementUI SPA单页面应用 ⊙Datagrid标签快速切换BootstrapTable列表风 ...

  8. 当spa单页面应用遇上SEO,蛋痛的经历

    spa单页面应用优点当然毋庸置疑:效果酷炫,我在视觉和产品面前无从反驳:性能高速度快,全JS嘛当然快,我在运维和产品面前无言以对:运算分散,异步加载,又省硬件又省流量,我在开发和产品面前彻底投降:JS ...

  9. 通过Blazor使用C#开发SPA单页面应用程序(1)

    2019年9月23--25日 .NET Core 3.0即将在.NET Conf上发布! .NET Core的发布及成熟重燃了.net程序员的热情和希望,一些.net大咖也在积极的为推动.NET Co ...

  10. SPA(单页面应用)和MPA(多页面应用)

    单页面应用 第一次进入页面时会请求一个html文件,刷新清除一下,切换到其他组件,此时路径也相应变化,但是并没有新的html文件请求,页面内容却变化了. 原理:js会感知到url的变化,通过这一点可以 ...

最新文章

  1. Docker Swarm Mode 学习笔记(聊聊 replicas)
  2. 【深度学习入门到精通系列】遗传算法 (Genetic Algorithm)
  3. 32位oracle和64位的区别,区分你的oracle是64位还是32位
  4. js导出excel单元格内换行符代码_前端和excel的那些事
  5. 什么是自然语言处理,它如何工作?
  6. php 大批量的删除图片,PHP批量删除记录同时删除图片文件
  7. spring boot mybatis 整合_Spring、MyBatis和SpringMVC的整合
  8. 工作五年的UI设计师,现在混的怎么样?不看是你的损失
  9. 电子计算机发展为第五代,电子计算机的发展历程是怎样的?
  10. PAT (Basic Level) Practice (中文)1043 输出PATest (20 分)
  11. Can't save in background: fork: Cannot allocate memory
  12. C#显示当前日期时间
  13. 2、linux网络编程--无连接与面向连接的区别
  14. 这一代系统,真的不行!(一)
  15. Python爬取、可视化分析B站大司马视频40W+弹幕
  16. 从前慢-谷粒商城篇章4
  17. 双差法(HYPODD)定位软件安装教程2
  18. 洛谷 [P1593 因子和] {快速幂+费马小定理求逆元+求解质因子} 奋斗的珂珂~
  19. html div 高度100,深入理解CSS的height:100%和height:inherit之间的使用区别
  20. 最新2016年苹果公司开发者帐号申请流程

热门文章

  1. php这个符号怎么打,怎么打出圈2符号
  2. MybatisPlus QueryWrapper(简称 QW,MP 封装的一个查询条件构造器)的使用和简单认识
  3. java-jacob操作word,往word中动态插入各种文件
  4. 自动阅读项目又出新情况?一天秒封47个账号
  5. 自动阅读是骗人的吗?新手一定要看,避免入坑
  6. GPA学分绩点计算---Java实现版本
  7. 安卓手机+LinuxDeploy+CentOS+宝塔面板的安装教程
  8. 如何创建用户和组?怎样添加用户呢?windows dos命令
  9. 生活细语:送给每一个热爱生活的人[ 收集整理,超强!!!]
  10. excel将一个工作表根据条件拆分成多个工作表图文教程