第一篇web 发展史
这篇主要是帮助我们qa 了解前端的历史与现状。
测试工程师大部分时间可能关注的是feature正确性,而对于前端代码级别的测试基本没有关心过,随着各种前端框架在web和移动端大行其道,绽放各种高大上的功能时,我们渐渐的发现前端代码级别问题逐渐暴露出来,甚至超越后端之势。那么问题来了,为什么以前这种现象出现呢?
我们现来看看前端技术发展史。
##石器时代——开荒阶段
带有简单逻辑的界面
最早期的Web界面基本都是在互联网上使用,而且基本都是静态页面展示,人们浏览某些内容,填写几个表单并且提交。当时的界面以浏览为主,基本都是HTML代码,我们来看一个最简单的HTML文件:
1 | <html> |
带有简单逻辑的界面
接下来我们发现使用一些工具可以帮助我们做一些业务处理,这时javascript到来了,开始大放异彩。这时的代码的组织比较简单,而且CSS的运用也是比较少的。譬如:下面这个文档将带有一段JavaScript代码,用于拼接两个输入框中的字符串,并且弹出窗口显示。
1 | <html> |
结合了服务端技术的混合编程
由于静态界面不能实现保存数据等功能,出现了很多服务端技术,早期的有CGI(Common Gateway Interface,多数用C语言或者Perl实现的),ASP(使用VBScript或者JScript),JSP(使用Java),PHP等等,Python和Ruby等语言也常被用于这类用途。
1 | <html> |
铁器时代—Ajax席卷全世界
AJAX
由于Ajax的出现,规模更大,效果更好的Web程序逐渐出现,在这些程序中,JavaScript代码的数量迅速增加。出于代码组织的需要,“JavaScript框架”这个概念逐步形成。
JavaScript基础库—jquery
Prototype框架主要是为JavaScript代码提供了一种组织方式,对一些原生的JavaScript类型提供了一些扩展,比如数组、字符串,又额外提供了一些实用的数据结构,如:枚举,Hash等,除此之外,还对dom操作,事件,表单和Ajax做了一些封装。
Mootools框架的思路跟Prototype很接近,它对JavaScript类型扩展的方式别具一格,所以在这类框架中,经常被称作“最优雅的”对象扩展体系。
从这两个框架的所提供的功能来看,它们的定位是核心库,在使用的时候一般需要配合一些外围的库来完成。
jQuery与这两者有所不同,它着眼于简化DOM相关的代码。
DOM的选择
jQuery提供了一系列选择器用于选取界面元素,在其他一些框架中也有类似功能,但是一般没有它的简洁、强大。
1 | $("*") //选取所有元素 |
链式表达式
在jQuery中,可以使用链式表达式来连续操作dom,比如下面这个例子:
1 | $("p.neat").addClass("ohmy").show("slow"); |
除此之外,jQuery还提供了一些动画方面的特效代码,也有大量的外围库,比如jQuery UI这样的控件库,jQuery mobile这样的移动开发库等等。
模块代码加载方式–Requirejs
以上这些框架提供了代码的组织能力,但是未能提供代码的动态加载能力。动态加载JavaScript为什么重要呢?因为随着Ajax的普及,jQuery等辅助库的出现,Web上可以做很复杂的功能,因此,单页面应用程序(SPA,Single Page Application)也逐渐多了起来。
单个的界面想要做很多功能,需要写的代码是会比较多的,但是,并非所有的功能都需要在界面加载的时候就全部引入,如果能够在需要的时候才加载那些代码,就把加载的压力分担了,在这个背景下,出现了一些用于动态加载JavaScript的框架,也出现了一些定义这类可被动态加载代码的规范。
在这些框架里,知名度比较高的是RequireJS,它遵循一种称为AMD(Asynchronous Module Definition)的规范。
例如下列是一个js代码保存为adder.js文件
1 | define(["math"], function(math) { |
当我们需要使用这个模块时,我们只需引入就好
1 | <script src="require.js"></script> |
RequireJS除了提供异步加载方式,也可以使用同步方式加载模块代码。AMD规范除了使用在前端浏览器环境中,也可以运行于nodejs等服务端环境,nodejs的模块就是基于这套规范定义的。(修订,这里弄错了,nodejs是基于类似的CMD规范的)
工业革命—前端框架
这个时期,随着Web端功能的日益复杂,人们开始考虑这样一些问题:
• 如何更好地模块化开发
• 业务数据如何组织
• 界面和业务数据之间通过何种方式进行交互
在这种背景下,出现了一些前端MVC、MVP、MVVM框架,我们把这些框架统称为MV*框架。这些框架的出现,都是为了解决上面这些问题,具体的实现思路各有不同,主流的有Backbone,AngularJS,Ember,Spine等等,本文主要选用Backbone和AngularJS来讲述以下场景。
数据模型
在这些框架里,定义数据模型的方式与以往有些差异,主要在于数据的get和set更加有意义了,比如说,可以把某个实体的get和set绑定到RESTful的服务上,这样,对某个实体的读写可以更新到数据库中。另外一个特点是,它们一般都提供一个事件,用于监控数据的变化,这个机制使得数据绑定成为可能。
在一些框架中,数据模型需要在原生的JavaScript类型上做一层封装,比如Backbone的方式是这样:
1 | var Todo = Backbone.Model.extend({ |
控制器
在Backbone中,是没有独立的控制器的,它的一些控制的职责都放在了视图里,所以其实这是一种MVP(Model View Presentation)模式,而AngularJS有很清晰的控制器层。
还是以这个todo为例,在AngularJS中,会有一些约定的注入,比如$scope,它是控制器、模型和视图之间的桥梁。在控制器定义的时候,将$scope作为参数,然后,就可以在控制器里面为它添加模型的支持。
1 | function TodoCtrl($scope) { |
视图
在这些主流的MV*框架中,一般都提供了定义视图的功能。在Backbone中,是这样定义视图的:
1 | // The DOM element for a todo item... |
最新内容请见作者的GitHub页:http://qaseven.github.io/