热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

前端程序员必知:单页面应用的核心

刚开始写商业代码的时候,我使用的是jQuery。使用jQuery来实现功能很容易,找到一个相应的jQuery插件,再编写相应的功能即可。对于单页面应用亦是如此,寻找一个相辅助的插件就可以了,如jQueryMobile。

刚开始写商业代码的时候,我使用的是 jQuery。使用 jQuery 来实现功能很容易,找到一个相应的 jQuery 插件,再编写相应的功能即可。对于单页面应用亦是如此,寻找一个相辅助的插件就可以了,如 jQuery Mobile。


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


尽管在今天看来,jQuery Mobile 已经不适合于今天的多数场景了。这个主要原因是,当时的用户对于移动 Web 应用的理解和今天是不同的。他们觉得移动 Web 应用就是针对移动设备而订制的,移动设备的 UI、更快的加载速度等等。而在今天,多数的移动 Web 应用,几乎都是单页面应用了。

过去,即使我们想创建一个单页面应用,可能也没有一个合适的方案。而在今天,可选择的方案就多了(PS:参见《第四章:学习前端只需要三个月【框架篇】》)。每个人在不同类型的项目上,也会有不同的方案,没有一个框架能解决所有的问题

  • 对于工作来说,我更希望的是一个完整的解决方案。
  • 对于编程体验来说,我喜欢一点点的去创造一些轮子。

当我们会用的框架越多的时候, 所花费的时间抉择也就越多。而单页面应用的都有一些相同的元素,对于这些基本元素的理解,可以让我们更快的适合其他框架。


单页面应用的演进


我接触到单页面应用的时候,它看起来就像是将所有的内容放在一个页面上么


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


只需要在一个 HTML 写好所需要的各个模板,并在不同的页面上 data-role 表明这是个页面(基于 jQuery Mobile)——每个定义的页面都和今天的移动应用的模式相似,有 header、content、footer 三件套。再用 id 来定义好相应的路由。

...

这样我们就在一个 HTML 里返回了所有的页面了。随后,只需要在在入口处的 href 里,写好相应的 ID 即可。

跳转到foo

当我们点击相应的链接时,就会切换到 HTML 中相应的 ID。这种简单的单页面应用基本上就是一个离线应用了,只适合于简单的场景,可是它带有单页面应用的基本特性。而复杂的应用,则需要从服务器获取数据。然而早期受限于移动浏览器性能的影响,只能从服务器获取相应的 HTML,并替换当前的页面。

在这样的应用中,我们可以看到单页面应用的基本元素: 页面路由,通过某种方式,如 URL hash 来说明表明当前所在的页面,并拥有从一个页面跳转到另外一个页面的入口。


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


当移动设备的性能越来越好时,开发者们开始在浏览器里渲染页面:

  • 使用 jQuery 来做页面交互
  • 使用 jQuery Ajax 来从服务端获取数据
  • 使用 Backbone 来负责路由及 Model
  • 使用 Mustache 作为模板引擎来渲染页面
  • 使用 Require.js 来管理不同的模板
  • 使用 LocalStorage 来存储用户的数据

通过结合这一系列的工具,我们终于可以实现一个复杂的单页面应用。而这些,也就是今天我们看到的单页面应用的基本元素。

我们可以在 Angular 应用、React 应用、Vue.js 应用 看到这些基本要素的影子,如:Vue Router、React Router、Angular 2 RouterModule 都是负责路由(页面跳转及模块关系)的。在 Vue 和 React 里,它们都是由辅助模块来实现的。因为 React 只是层 UI 层,而 Vue.js 也是用于构建用户界面的框架。


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



前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


要说起路由,那可是有很长的故事。当我们在浏览器上输入网址的时候,我们就已经开始了各种路由的旅途了。

浏览器会检查有没有相应的域名缓存,没有的话就会一层层的去向 DNS服务器 寻向,最后返回对应的服务器的 IP 地址。

接着,我们请求的网站将会将由对应 IP 的 HTTP 服务器处理,HTTP 服务器会根据请求来交给对应的应用容器来处理。

随后,我们的应用将根据用户请求的路径,将请求交给相应的函数来处理。最后,返回相应的 HTML 和资源文化

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


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


如 Python 语言里的 Web 开发框架 Django 的 URLConf,使用正规表达式来表正

url(r'^articles/2003/$', views.special_case_2003),

而在 Laravel 里,则是通过参数的形式来呈现

Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) { //});

虽然表现形式有一些差别,但是总体来说也是差不多的。而对于前端应用来说,也是如此,将对应的 URL 的逻辑交由对应的函数来处理

React Router 使用了类似形式来处理路由,代码如下所示:

当页面跳转到 blog 的时候,会将控制权将给 BlogList 组件来处理。

当页面跳转到 blog/fasfasf-asdfsafd 的时候,将匹配到这二个路由,并交给 BlogDetail 组件 来处理。而路由中的 id 值,也将作为参数 BlogDetail 组件来处理。

相似的,而 Angular 2 的形式则是:

{ path: 'blog', component: BlogListComponent },{ path: 'blog/:id', component: BlogDetailComponent },

相似的,这里的 BlogDetailComponent 是一个组件,path 中的 id 值将会传递给 BlogDetailComponent 组件。

从上面来看,尽管表现形式上有所差异,但是其行为是一致的:使用规则引擎来处理路由与函数的关系。稍有不同的是,后台的路由完全交由服务器端来控制,而前端的请求则都是在本地改变其状态。


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


并且同时在不同的前端框架上,他们在行为上还有一些区别。这取决于我们是否需要后台渲染,即刷新当前页面时的表现形式。

使用 Hash (#)或者 Hash Bang (#!) 的形式。即 # 开头的参数形式,诸如 ued.party/#/blog。当我们访问 blog/12 时,URL 的就会变成 ued.party/#/blog/12

使用新的 HTML 5 的 history API。用户看到的 URL 和正常的 URL 是一样的。当用户点击某个链接进入到新的页面时,会通过 history 的 pushState 来填入新的地址。当我们访问 blog/12 时,URL 的就会变成 ued.party/blog/12。当用户刷新页面的时候,请通过新的 URL 来向服务器请求内容。

幸运的是,大部分的最新 Router 组件都会判断是否支持 history API,再来决定先用哪一个方案。


数据:获取与鉴权


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


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


对于数据获取来说,我们可以通过封装过 XMLHttpRequest 的 Ajax 来获取数据,也可以通过新的、支持 Promise 的 Fetch API 来获取数据,等等。Fetch API 与经过 Promise 封装的 Ajax 并没有太大的区别,我们仍然是写类似于的形式:

fetch(url).then(respOnse=> response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))

对于复杂一点的数据交互来说,我们可以通过 RxJS 来解决类似的问题。整个过程中,比较复杂的地方是对数据的鉴权与模型(Model)的处理。

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

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


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


一旦谈论到数据的时候,不可避免的我们就需要关心安全因素。对于普通的 Web 应用来说,我们可以做两件事来保证数据的安全:

  • 采用 HTTPS:在传输的过程中保证数据是加密的。
  • 鉴权:确保指定的用户只能可以访问指定的数据。

目前,流行的前端鉴权方式是 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 就比较容易找到调用的地方。


用户交互:事件


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


前端程序员必知:单页面应用的核心前端程序员必知:单页面应用的核心


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


推荐阅读
  • Jquery 跨域问题
    为什么80%的码农都做不了架构师?JQuery1.2后getJSON方法支持跨域读取json数据,原理是利用一个叫做jsonp的概念。当然 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
author-avatar
别样青年别样范儿bo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有