浅谈SPA

  最近一直在学习关于Vue的一些知识,因为遇到了问题,去网上查找资料,收获颇丰,在此分享。javascript

1. 什么是SPA?

  单页Web应用(single page web application, SPA),就是只有一张Web页面的应用,是加载单个HTML页面并在用户与应用程序交互时动态更新该页面的Web应用程序,是指在浏览器中运行的应用,在使用期间不会从新加载页面。像全部的应用同样,它旨在帮助用户完成任务,好比“编写文档”或者“管理Web服务器”。能够认为单页应用是一种从Web服务器加载的富客户端。css

  速度:更好的用户体验,让用户在web app感觉native app的速度和流畅,
  MVC:经典MVC开发模式,先后端各负其责,后端只须要提供数据接口
  ajax:重前端,业务逻辑所有在本地操做,数据都须要经过AJAX同步、提交。
  路由:在URL中采用#号来做为当前视图的地址,改变#号后的参数,页面并不会重载,这个也就是哈希。html

  

  SPA也是当今网站开发技术的一种趋势和潮流,毕竟前端三大框架不是盖的~~,不少的传统网站都在或者已经转型为单页Web应用,新的单页Web应用网站(包括移动端平台上面的)也雨后春笋涌现出来。前端

  单页Web应用和前端工程师们息息相关,由于主要的变革发生在浏览器端,用到的技术其实仍是HTML+CSS+JavaScript,全部的浏览器都原生支持,固然有的浏览器由于具有一些高级特性,从而使得单页Web应用的用户体验更上一层楼。关于单页应用的优势和缺点,下一个问题就说。 单页Web应用,顾名思义,就是只有一张Web页面的应用。浏览器一开始会加载必需的HTML、CSS和JavaScript,以后全部的操做都在这张页面上完成,这一切都由JavaScript来控制。所以,单页Web应用会包含大量的JavaScript代码,复杂度可想而知,模块化开发和设计的重要性不言而喻。java

单页Web应用程序的优势:

  1.首先,最大的好处是用户体验,对于内容不改动的不须要加载整个页面。这样作好处颇多,由于数据层是和UI的分离,能够从新编写一个原生的移动设备应用程序而不用(对原有数据服务部分)大动干戈。ios

  2.单页面Web应用层程序最根本的优势是高效。它对服务器压力很小,消耗更少的带宽,可以与面向服务的架构更好地结合。web

单页Web应用程序的缺点:

  虽然还有一些历史遗留问题(大部分是针对HTML5的改进)以及SEO。若是你看中SEO,那你应该使用网站而不是Web应用。目前该技术还存在一些争议,但这并非重点,由于这种类型的体系架构为SAAS Web Apps提供了一个极大的可用性。ajax

  

程序结构 -- 重点

  单页Web应用程序的结构很简单:首先传递HTML文档框架;而后使用JavaScript修改页面;紧接着再从服务器传递更多数据而后再修改页面,如此循环。从性能的角度看,在现代浏览器中单页面Web App已经可以和普通应用程序相媲美,并且几乎全部的操做系统都支持现代的浏览器。使用HTML+CSS+JavaScript编写应用程序,能使更多的人们都加入到程序开发的行列。axios

  这足以说明,在Web设计过程当中标志着Web将呈现一种新的趋势,它将一个分离的功能层做为API并将表示层用APP的形式体现出来(HTML5或Native)后端

  • 单页面+API模式比基于应用程序的HTML多重页面更加灵活,由于底层API可用于多种不一样的上下文、形式因素和设备类型。一旦网页内置了API,可以知足客户不一样需求(好比合做伙伴vs最终用户)。
  • 该模式意味着本地Web应用可以为用户不管是基于什么平台提供更接近一个本地移动或桌面应用程序的体验。
  • 协议(如openAuth(oAuth))成为做为用户受权的黄金标准已被普遍采用,提供了一个共同的模式。从应用程序好饿内容中将单独登陆/受权问题分离出来。也就是说用户的身份能够从内容、功能和用户体验中清晰的分离出。

  一个单页面Web应用程序就是一个Web应用程序,但结构哦不一样。其中最重要的是:在第一次请求的时候,全部的标记语言(HTML)就已经传输到客户端,其他的请求都经过REST API获取JSON数据,数据的传输经过Web Socket API或远程过程调用。单页面应用程序能够说是分拆Web技术的最后一步----经过分离(css)内容,改进架构(XML和XSLT)上的灵活性,调用服务器(AJAX)再到解压应用程序的导航页面结构,所以,这在Web发展中是个历史性的转折点。

  目前这只是单页面Web应用开发的初期,但能够看出将单页面应用、APIs以及JavaScript结合在一块儿将成为许多流行应用的规范。

  因此,当被问到“HTML5是App+API?”,咱们会说,“二者皆是---”将二者结合在一块儿要比以往快得多。“单页面应用是一块很是大的拼图。固然,导航、历史性和SEO等问题也成为单页面Web应用的诟病”

 

单页面应用的演进

  在这里介绍一些Hash的内容先,单页面应用是如何实现不刷新网页而进行跳转的呢?

 

HTML中的hash(#号)

  

1.#的含义

  #表明网页中的一个位置。右面的自负就是表明的位置信息:如

  http://localhost:8080/cbuild/index.html#one

  就表明网页index.html的one位置。浏览器读取这个URL后,会自动将one位置滚动至可视区域。

 

    为网页制定标识符:

    一是使用锚点  好比 <a name="print"></a>

    二是使用id属性,好比<div id="print"></div>

2.HTTP请求不包括#

  好比: http://localhost:8081/cbuild/index.html#first

  浏览器实际发出的请求是这样的

  GET/index.html  

  而不包含 #first

3.#后的字符

  在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。

  好比,下面URL的原意是指定一个颜色值:

     http://www.example.com/?color=#fff

   可是,浏览器实际发出的请求是:

  GET/?color=

  Host: www.example.com

   能够看到,“#fff”被省略了,只有将#转码为$23,浏览器才会将其做为实义字符处理。也就是说,上面的网址应该被写成:

  http://www.example.com/?color=%23fff

4、改变#不触发网页重载

  单单改变#后的部分,浏览器只会滚动到相应位置,不会从新加载网页。

  好比,从

  http://www.example.com/index.html#location1

   改变到

  http://www.example.com/index.html#location2

   浏览器不会从新向服务器请求index.html

5、改变#会改变浏览器的访问历史

  每一次改变#后的部分,都会在浏览器的访问历史中增长一个记录,使用"后退"按钮,就能够回到上一个位置。

  这对于ajax应用程序特别有用,能够用不一样的#值,表示不一样的访问状态,而后向用户给出能够访问某个状态的连接。

  值得注意的是,上述规则对IE6和IE7不成立,它们不会由于#的改变而增长历史记录

6、window.location.hash读取#值

  window.location.hash这个属性可读可写。读取时,能够用来判断网页状态是否改变;写入时,则会在不重载网页的前提下,创造一条访问历史记录。

7、onhashchange事件

  这是一个HTML5新增的事件,当#值发生变化时,就会触发这个事件。IE8+、Firefox 3.6+、Chrome 5+、Safari 4.0+支持该事件。

  它的使用方法有三种:

  

1 window.onhashchange = func;
2 <body onhashchange="func();">
3 window.addEventListener("hashchange",func, false);

 

  对于不支持onhashchange的浏览器,能够用setInterval监控location.hash的变化。

8、Google抓取#的机制

  默认状况下,Google的网络蜘蛛忽视URL的#部分。

  可是,Google还规定,若是你但愿Ajax生成的内容被浏览引擎读取,那么URL中可使用"#!",Google会自动将其后面的内容转成查询字符串_escaped_fragment_的值。

  好比,Google发现新版twitter的URL以下:

  http://twitter.com/#!/username

  就会自动抓取另外一个URL:

  http://twitter.com/?_escaped_fragment_=/username

  经过这种机制,Google就能够索引动态的Ajax内容。

  单页面Web应用就是根据上述的#,监控#值的改变去对应的改变页面。

 

路由:页面跳转与模块关系

  要提及路由,那但是有很长的故事。当咱们在浏览器上输入网址的时候,咱们就已经开始了各类路由的旅途了。

  1. 浏览器会检查有没有相应的域名缓存,没有的话就会一层层的去向 DNS服务器 寻向,最后返回对应的服务器的 IP 地址。
  2. 接着,咱们请求的网站将会将由对应 IP 的 HTTP 服务器处理,HTTP 服务器会根据请求来交给对应的应用容器来处理。
  3. 随后,咱们的应用将根据用户请求的路径,将请求交给相应的函数来处理。最后,返回相应的 HTML 和资源文化

  当咱们作后台应用的时候,咱们只须要关心上述过程当中的最后一步。即,将对应的路由交给对应的函数来处理。这一点,在不一样的后台框架的表现形式都是类似的。

  虽然表现形式有一些差异,可是整体来讲也是差很少的。而对于前端应用来讲,也是如此,将对应的 URL 的逻辑交由对应的函数来处理。

  使用规则引擎来处理路由与函数的关系。稍有不一样的是,后台的路由彻底交由服务器端来控制,而前端的请求则都是在本地改变其状态,而且同时在不一样的前端框架上,他们在行为上还有一些区别。这取决于咱们是否须要后台渲染,即刷新当前页面时的表现形式。

数据:获取与鉴权

  实现路由的时候,只是将对应的控制权交给控制器(或称组件)来处理。而做为一个单页面应用的控制器,当执行到相应的控制器的时候,就能够根据对应的 blog/12 来获取到用户想要的 ID 是 12。这个时候,控制器将须要在页面上设置一个 loading 的状态,而后发送一个请求到后台服务器。

  对于数据获取来讲,咱们能够经过axios,咱们仍然是写相似于的形式:

1 axios.get(url)
2     .then(res=>{
3         console.log(res.data)
4     })
5     .catch(err=>{
6         console.log(err);
7         throw err;
8     })

  模型麻烦的地方在于:转变成想要的形式。后台返回的值是可变的,它有可能不返回,有多是 null,又或者是与咱们要显示的值不同——想要展现的是 54%,然后台返回的是 0.54。与此同时,咱们可能还须要对数值进行简单的计算,显示一个范围、区间,又或者是不一样的两种展现。

  同时在必要的时候,咱们还须要将这些值存储在本地,或者内存里。当咱们从新进入这个页面的时候,咱们再去读取这些值。

  一旦谈论到数据的时候,不可避免的咱们就须要关心安全因素。对于普通的 Web 应用来讲,咱们能够作两件事来保证数据的安全:

  1. 采用 HTTPS:在传输的过程当中保证数据是加密的。
  2. 鉴权:确保指定的用户只能能够访问指定的数据。

  目前,流行的前端鉴权方式是 Token 的形式,能够是普通的定制 Token,也能够是 JSON Web Token。获取 Token 的形式,则是经过 Basic 认证——将用户输入的用户名和密码,通过 BASE64 加密发送给服务器。服务器解密后验证是不是正常的用户名和密码,再返回一个带有时期期限的 Token 给前端。

  随后,当用户去获取须要权限的数据时,须要在 Header 里鉴定这个 Token 是否有限,再返回相应的数据。若是 Token 已通过期了,则返回 401 或者相似的标志,客户端就在这个时候清除 Token,并让用户从新登陆。

数据展现:模板引擎

  如今,咱们已经获取到这些数据了,下一步所须要作的就是显示这些数据。与其余内容相比,显示数据就是一件简单的事,无非就是:

  • 依据条件来显示、隐藏某些数据
  • 在模板中对数据进行遍历显示
  • 在模板中执行方法来获取相应的值,能够是函数,也能够是过滤器。
  • 依据不一样的数值来动态获取样式
  • 等等

  不一样的框架会存在一些差别。而且现代的前端框架均可以支持单向或者双向的数据绑定。当相应的数据发生变化时,它就能够自动地显示在 UI 上。

  最后,在相应须要处理的 UI 上,绑上相应的事件来处理。

  是在数据显示的时候,又会涉及到另一个问题,即组件化。对于一些须要重用的元素,咱们会将其抽取为一个通用的组件,以便于咱们能够复用它们,而且在这些组件里,也会涉及到相应的参数变化即状态改变。

  

交互:事件与状态管理

  完成一步步的渲染以后,咱们还须要作的事情是:交互。交互分为两部分:用户交互、组件间的交互——共享状态。

组件交互:状态管理

  用户从 A 页面跳转到 B 页面的时候,为了解耦组件间的关系,咱们不会使用组件的参数来传入值。而是将这些值存储在内存里,在适当的时候调出这些值。当咱们处理用户是否登陆的时候,咱们须要一个 isLogined 的方法来获取用户的状态;在用户登陆的时候,咱们还须要一个 setLogin 的方法;用户登出的时候,咱们还须要更新一下用户的登陆状态。

  在没有 Redux 以前,我都会写一个 service 来管理应用的状态。在这个模块里写上些 setter、getter 方法来存储状态的值,并根据业务功能写上一些来操做这个值。然而,使用 service 时,咱们很难跟踪到状态的变化状况,还须要作一些额外的代码来特别处理。

  有时候也会犯懒一下,直接写一个全局变量。这个时候维护起代码来就是一场噩梦,须要全局搜索相应的变量。若是是调用某个特定的 Service 就比较容易找到调用的地方。

用户交互:事件

  事实上,对于用户交互来讲也只是改变状态的值,即对状态进行操做。

  一个例子,当用户点击登陆的时候,发送数据到后台,由后台返回这个值。由控制器一一的去修改这些状态,最后确认这个用户登陆,并发一个用户已经登陆的广播,又或者修改全局的用户值。

  

  这里先介绍这么多。

  本文参考文章:

  一篇外国文章: HTML,JavaScript和Web的应用程序      

  做者:明铭之中  HTML中的hash(#号)   

  做者: mongkey_king  SPA   

  做者:刘贵生 关于Vue项目的seo问题

  

  这里总结了一下他们的一些文章,方便之后查阅,看他们的文章让我收获颇多,一瞬间感慨万千,技术发展太快,咱们只能默默坚持,学习新的技术,争取本身也有机会作那一头领头羊。

  若是你看了个人文章感受学习到了一些知识,那我很是高兴。做者水平有限,若有不足之处,还望指正。

相关文章
相关标签/搜索