在早期的 Web 应用中,前端的作用很弱,业务逻辑和数据处理都在后端,后端给前端返回一个 HTML 页面,前端只负责展示。在这种模式下,单个 HTML 页面被当做一个功能原件,表单提交,超链接跳转都可以用来重新请求新的 HTML 页面,从而达到给用户展示新的页面的目的。在这种方式中,你可以感觉到页面总是在不停的刷新,一个点击可能都需要等待很久,这是因为,当页面变化时,所有资源都需要重新请求。这些问题导致了用户体验不佳,也浪费了资源。单页应用便很好的解决了这些问题。

概念

什么是单页应用呢?单页应用的全称是 single-page application,简称 SPA,它是一种网站应用的模型,它可以动态重写当前的页面来与用户交互,而不需要重新加载整个页面。单页应用的流畅性让 Web 应用更像桌面端或 Native 应用了。相对于传统的 Web 应用,单页应用做到了前后端分离,后端只负责处理数据提供接口,页面逻辑和页面渲染都交给了前端。前端发展到现在,单页应用的使用已经很广泛,目前时兴的 React、Vue、Angular 等前端框架均采用了 SPA 原则。单页应用意味着前端掌握了主动权,也让前端代码更复杂和庞大,模块化、组件化以及架构设计都变得越来越重要。

来体验一下单页应用吧,打开你的 Gmail,点击左侧的导航栏,在开发者工具的 Network 中可以看到资源是按需加载的,此时页面也并没有刷新,观察 Elements 栏下的 HTML,你会发现整个 HTML 的大框架是不变的,页面改变时,或者说路由改变时,DOM 树只是改变它需要改变的部分,也就是动态改变。

工作原理

SPA 的一个重要实现就是改变路由时,页面不刷新。实现这个功能,通常有两种方式:使用 window.history 对象或 location.hash。

history 对象

window.history 包含了浏览器的历史信息,它有以下几种常用方法:

history.back():与在浏览器点击后退按钮相同;history.forward():与在浏览器中点击按钮向前相同;history.go(n):接受一个整数作为参数,移动到该整数指定的页面,比如 go(1) 相当于 forward(),go(-1) 相当于 back(),go(0) 相当于刷新当前页面。HTML5 对 history 对象新增了 pushState() 和 replaceState() 方法,这两个方法可以往历史栈中添加数据,给用户的感觉就是浏览器的 url 改变了,但是页面并没有重新加载。pushState() 是在浏览记录中添加一个新记录,replaceState() 则是修改当前的浏览器记录,这是二者的细微差别,使用时参数的字段和含义都是一样的。

window.history.pushState(state, title, url)

state 是状态对象,可以用 history.state 读取;title 表示新页面的标题,但是现在的所有浏览器都会忽略这个字段,所以可以传 null;url 是新页面的地址,必须是和当前页面在同一个域。当用户点击浏览器上的前进和后退按钮时,或者调用上述 window.history 的 back、forward 和 go 方法,就会触发 popstate 事件。该事件只针对同一个文档,如果浏览历史的切换导致加载了不同的文档,popstate 事件将不会被触发。popstate 事件回调函数的参数中的 state 属性指向 pushState() 和 replaceState() 方法为当前页面提供的状态,也就是 pushState() 和 replaceState() 方法使用时传的第一个参数 state。

我们可以通过 pushState() 简单模拟一下浏览器的路由改变且不刷新页面。

<aclass="spa">spa1.html</a><aclass="spa">spa2.html</a><buttonοnclick="goBack()">back</button><buttonοnclick="goForward()">back</button>

document.querySelectorAll('.spa').forEach((item, index)=>{ item.addEventListener('click',(e)=>{ e.preventDefault();let link = item.textContent; window.history.pushState({name:`spa${index +1}`}, link, link) console.log(link,'pushState')},false)})window.addEventListener('popstate',(e)=>{ console.log(e.state)})functiongoBack(){ window.history.back()}functiongoForward(){ window.history.forward()}

通过监听点击事件,使用 pushState() 来修改 history 对象,下面的 gif 图演示了这个过程。需要注意的是,pushState() 和 replaceState() 方法只能修改路由,并不能让页面重新渲染。浏览器地址栏显示 demo/spa2.html 时,并不会跳转到 spa2.html 页面,也不会检查 spa2.html 页面是否存在,只是使其成为浏览器历史中的最新记录。

(使用 history 对象改变路由)

hash

hash 是 location 对象的属性,它指的是当前 url 的锚,也就是从 # 号开始的部分。修改 location.hash 并监听 window 的 hashchange 事件,也能达到同样的目的。

<aclass="spa">spa1.html</a><aclass="spa">spa2.html</a>

document.querySelectorAll('.spa').forEach((item, index)=>{ item.addEventListener('click',(e)=>{ e.preventDefault(); location.hash = index +1},false)})window.addEventListener('hashchange',(e)=>{ console.log({ hash: location.hash })})

演示效果如下:

(使用 hash 改变路由)

优缺点

SPA 可圈可点,现在已被大家广泛使用,也得到了主流框架的支持,但是它也有局限性,我们将它的优缺点总结如下。

优点有:

无刷新体验,用户在切换页面过程中不会频繁被“打断”,因为界面框架都在本地,对用户的响应非常及时,因此提升了用户体验;分离前后端关注点,前端负责界面显示,后端负责数据存储和计算,各司其职,不会把前后端的逻辑混杂在一起;减轻服务器压力,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍;API 共享,同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端;完全的前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方式更加规范化,便于修改和调整。缺点有:

对 SEO 不太优好,尽管可以通过 Prerender 预渲染优化等技术解决一部分,但是相对还是不容易索引到它;易出错,需要使用程序管理前进、后退、地址栏等信息;较高的前端开发门槛,对技术能力要求较高,需要对设计模式有一定理解,因为面对不是一个简单的页面,而是一个运行在浏览器环境里面的桌面软件。小结

在本节中,我们简单理解了 SPA 以及 SPA 在路由层面的实现,在这一小节中,你需要掌握:

理解 SPA 是什么;SPA 路由的工作原理;了解 SPA 的优缺点。

什么是单页面应用(竞价单页面)相关推荐

  1. 前端的单页面模式和多页面模式

    一.前言 前端部分的搭建,需要考虑使用哪种模式进行页面之间的跳转交互, 而项目内的页面交互,不可避免的需要相互之间的数据共享. 这就引出了本篇博客的目的,一起来谈谈:项目前端部分的构建方式以及数据共享 ...

  2. 浏览器--如何让登陆页面的表单不默认显示账号和密码

    2019独角兽企业重金招聘Python工程师标准>>> 楼主做Javaweb项目,制作登陆页面访问时总是出现用户名和密码被自动填写的情况:如图楼主自制的网页登陆页面(这里以楼主用的C ...

  3. html页面关闭前提示信息,【转】表单提交及关闭当前页面并刷新数据

    在DWZ文档中,对于DWZ框架Ajax无刷新表单提交处理流程描述如下: 1.       ajax表单提交给服务器 2.       服务器返回一个固定格式json结构 3.       js会调函数 ...

  4. 移动Web单页应用开发实践——页面结构化

    1. 前言 在开发面向现代智能手机的移动Web应用的时候,无法避免一个事实,就是需要开发单页应用(Single Page WebApp).对于不同的系统需求,单页应用的粒度会不同,可能是整个系统都使用 ...

  5. seo需要处理页面html,为什么单页面的seo不友好?如何解决这一问题?

    前言 大家可能都知道单页面的SEO不友好,但是你有没有思考过为什么单页面的SEO不友好呢?在单页面盛行的今天,有哪些策略来规避掉这一缺点呢?很好奇有木有?那就跟我一起开启探索之旅吧~ 搜索引擎的工作原 ...

  6. 用java写注册表单_利用HTML表单标签编写一个注册页面

    今天我们来写一个注册页面 form表单 先来利用表单标签制作一个简单的注册页面,给大家说说标签的结构: 页面结构大体就是这样子的~ 利用HTML表单标签编写一个注册页面 表单标签: 所有需要提交到服务 ...

  7. vue.js能美化界面吗_vue将单页面改造成多页面应用的方法

    问题描述: 手头有一个项目是使用 vue-cli 搭建的单页面应用.项目分为了管理平台和用户查看页面,用户查看页面是很简单的页面,但是在加载过程中,却加载了整个应用的打包代码,量重且影响了响应和体验. ...

  8. B端页面——详细表单设计流程

    一.什么是表单? 表单设计是B端产品设计的基础页面,想要做好表单设计首先要搞清楚表单的应用场景. 表单是用户采集数据信息的核心场景,同时又通过表单向用户展示数据信息,简而言之表单是用户与数据库之间的桥 ...

  9. vue如何在一个工程里判断h5还是pc,(利用在一个页面显示不同router-view内容原理,本文只使用于单页面项目,多页面项目请查看我另一篇博文)

    本文只适用于单页面项目,多页面项目请查看我另一篇博文 vue如何在一个工程里显示pc和手机端(适用多页面复杂项目) https://blog.csdn.net/qq_37816525/article/ ...

  10. 单页面SPA和多页面MPA应用的区别

    单页面应用SPA 概念:只有一个html页面,所有跳转方式都是通过组件切换来完成的. 路由不是后端来做了,而是前端来做,判断页面到底是显示哪个组件,清除不需要的,显示需要的组件.这种过程就是单页应用, ...

最新文章

  1. OSChina 周六乱弹 —— 就少个接吻的女友了
  2. java中关于时间的计算
  3. 怎么在S4 HANA中使用40位物料编码
  4. 将功补过 树形动态规划
  5. C++ 二维数组示例 - 控制台和MFC版
  6. 链接器怎样使用静态库来解决符号引用
  7. 万字长文 | 漫谈libco协程设计及实现
  8. C++描述杭电OJ 2018.母牛的故事 ||
  9. 加快Vue项目的开发速度
  10. SAP License:Payment Terms 付款条件
  11. OpenJDK 中脏话太多,开发者看不下去了
  12. redis memcache 性能比较
  13. Cocos2d Box2D之浮动刚体
  14. mysql 查看修改连接数据库_mysql查看最大连接数和修改mysql数据库最大连接数方法...
  15. C# 字符串转JSON格式
  16. 计量单位报错:消息号BM302 “未使用语言 ZH 创建单位 XXX”
  17. 倾斜摄影超大场景的三维模型轻量化与三维展示效果的关系浅析
  18. 国内VR体验馆发展现状及未来前景
  19. 装机不求人,10 分钟电脑配置挑选速成攻略
  20. 极进网络将收购斑马技术的无线局域网业务并获蓝筹客户

热门文章

  1. php 二级下拉菜单源码,二级联动菜单-PHP源码
  2. BPR贝叶斯个性化推荐算法—推荐系统基础算法(含python代码实现以及详细例子讲解)
  3. 无限风光在险峰:你真想创业?
  4. android studio 布局拖拽,为什么使用android studio不能像老师一样在Design里随意拖动控件...
  5. 色彩模型--ps课程笔记
  6. 下载安装SQL Sever 2022全过程
  7. 紧急:EIMS安全补丁,大家快补
  8. (C语言篇)static关键字
  9. springboot毕设项目班级综合测评管理系统ljm7u(java+VUE+Mybatis+Maven+Mysql)
  10. Latex公式换行时出现 Environment aligned undefined.