前端进化史
突然好奇前端的历史由来。记录下来。
这是一个众所周知的故事。说来好笑:如今奠定前端基石的javascript这门语言刚开始被开发出来时仅仅是为了处理以前有服务器端语言负责的一些输入验证操作。次年,Netscape公司就发布了浏览器端语言javascript,并且向ecma国际提交了将该javascript作为工业化标准的申请,逐渐的便有了ECMAScript这个标准。ECMA-262的第三版在1999年12月发布。在2009年1月,旨在为javascript离开浏览器端开发而建立的一套共同的标准库而成立的项目CommonJs产生,而且目前是作为最好的后端编程语言之一。
前端开发技术,从狭义看就是围绕HTML,css,javascript的这样一套体系的开发技术。它的运行宿主是浏览器。从前端技术的发展来看:大致分为以下几个阶段:
一.刀耕火种
最早的了web界面主要是用来浏览的,主要以html为主,最多加点javascript脚本填写表单并且提交。这个时候的css也用的比较少。
几个例子:
<html> <head> <title>测试二</title> </head> <body> <input id="firstNameInput" type="text" /> <input id="lastNameInput" type="text" /> <input type="button" onclick="greet()" /> <script language="JavaScript"> function greet() { var firstName = document.getElementById("firstNameInput").value; var lastName = document.getElementById("lastNameInput").value; alert("Hello, " + firstName + "." + lastName); } </script> </body> </html>
但是由于静态页面不能实现保存数据等功能,出现了很多服务端技术,早起的有CGI,ASP,JSP,PHP等等。有了这类技术,在HTML中就可以使用表单的post功能提交数据了,比如:
<form method="post" action="username.asp"> <p>First Name: <input type="text" name="firstName" /></p> <p>Last Name: <input type="text" name="lastName" /></p> <input type="submit" value="Submit" /> </form>
在这个阶段,由于客户端和服务端的职责未作明确的划分,比如生成一个字符串,可以由前端的JavaScript做,也可以由服务端语言做,所以通常在一个界面里,会有两种语言混杂在一起,用<%和%>标记的部分会在服务端执行,输出结果,甚至经常有把数据库连接的代码跟页面代码混杂在一起的情况,给维护带来较大的不便。
<html> <body> <p>Hello world!</p> <p> <% response.write("Hello world from server!") %> </p> </body> </html>
组件化的萌芽:
这个时代,也逐渐出现了组件化的萌芽。比较常见的有服务端的组件化,比如把某一类服务端功能单独做成片段,然后其他需要的地方来include进来,典型的有:ASP里面数据库连接的地方,把数据源连接的部分写成conn.asp,然后其他每个需要操作数据库的asp文件包含它。
上面所说的是在服务端做的,浏览器端通常有针对JavaScript的,把某一类的Javascript代码写到单独的js文件中,界面根据需要,引用不同的js文件。针对界面的组件方式,通常利用frameset和iframe这两个标签。某一大块有独立功能的界面写到一个html文件,然后在主界面里面把它当作一个frame来载入,一般的B/S系统集成菜单的方式都是这样的。
此外,还出现了一些基于特定浏览器的客户端组件技术,比如IE浏览器的HTC(HTML Component)。这种技术最初是为了对已有的常用元素附加行为的,后来有些场合也用它来实现控件。微软ASP.net的一些版本里,使用这种技术提供了树形列表,日历,选项卡等功能。HTC的优点是允许用户自行扩展HTML标签,可以在自己的命名空间里定义元素,然后,使用HTML,JavaScript和CSS来实现它的布局、行为和观感。这种技术因为是微软的私有技术,所以逐渐变得不那么流行。
Firefox浏览器里面推出过一种叫XUL的技术,也没有流行起来。
二.铁器时代
这个时代典型特征就是Ajax的出现。
1.Ajax
AJAX其实是一系列已有技术的组合,早在这个名词出现之前,这些技术的使用就已经比较广泛了,GMail因为恰当地应用了这些技术,获得了很好的用户体验。
由于Ajax的出现,规模更大,效果更好的Web程序逐渐出现,在这些程序中,JavaScript代码的数量迅速增加。出于代码组织的需要,“JavaScript框架”这个概念逐步形成,当时的主流是prototype和mootools,这两者各有千秋,提供了各自方式的面向对象组织思路。
2.javascript基础库
Prototype框架主要是为JavaScript代码提供了一种组织方式,对一些原生的JavaScript类型提供了一些扩展,比如数组、字符串,又额外提供了一些实用的数据结构,如:枚举,Hash等,除此之外,还对dom操作,事件,表单和Ajax做了一些封装。
Mootools框架的思路跟Prototype很接近,它对JavaScript类型扩展的方式别具一格,所以在这类框架中,经常被称作“最优雅的”对象扩展体系。
从这两个框架的所提供的功能来看,它们的定位是核心库,在使用的时候一般需要配合一些外围的库来完成。
jQuery与这两者有所不同,它着眼于简化DOM相关的代码。 例如:
- DOM的选择
jQuery提供了一系列选择器用于选取界面元素,在其他一些框架中也有类似功能,但是一般没有它的简洁、强大。
$("*") //选取所有元素 $("#lastname") //选取id为lastname的元素 $(".intro") //选取所有class="intro"的元素 $("p") //选取所有<p>元素 $(".intro.demo") //选取所有 class="intro"且class="demo"的元素
- 链式表达式:
在jQuery中,可以使用链式表达式来连续操作dom,比如下面这个例子:
如果不使用链式表达式,可能我们需要这么写:
var neat = $("p.neat"); neat.addClass("ohmy"); neat.show("slow"); //有了链式表达式,就可以这样一行代码完成; $("p.neat").addClass("ohmy").show("slow");
除此之外,jQuery还提供了一些动画方面的特效代码,也有大量的外围库,比如jQuery UI这样的控件库,jQuery mobile这样的移动开发库等等。
3.模块代码加载方式:
以上这些框架提供了代码的组织能力,但是未能提供代码的动态加载能力。动态加载JavaScript为什么重要呢?因为随着Ajax的普及,jQuery等辅助库的出现,Web上可以做很复杂的功能,因此,单页面应用程序(SPA,Single Page Application)也逐渐多了起来。单个的界面想要做很多功能,需要写的代码是会比较多的,但是,并非所有的功能都需要在界面加载的时候就全部引入,如果能够在需要的时候才加载那些代码,就把加载的压力分担了,在这个背景下,出现了一些用于动态加载JavaScript的框架,也出现了一些定义这类可被动态加载代码的规范。
在这些框架里,知名度比较高的是RequireJS,它遵循一种称为AMD(Asynchronous Module Definition)的规范。
比如下面这段,定义了一个动态的匿名模块,它依赖math模块:
define(["math"], function(math) { return { addTen : function(x) { return math.add(x, 10); } }; });
假设上面的代码存放于adder.js中,当需要使用这个模块的时候,通过如下代码来引入adder:
<script src="require.js"></script> <script> require(["adder"], function(adder) { //使用这个adder }); </script>
三.工业革命
这个时期,随着Web端功能的日益复杂,人们开始考虑这样一些问题:
1.如何更好的模块化开发;
2.业务数据如何组织;
3.界面和业务数据之间通过何种方式进行交互。
在这种背景下,出现了一些前端MVC、MVP、MVVM框架,我们把这些框架统称为MV*框架。这些框架的出现,都是为了解决上面这些问题,具体的实现思路各有不同,主流的有Backbone,AngularJS,Ember,Spine等等,下篇主要选用Backbone和AngularJS来讲述一些相关场景。