WEB技术面面观

超文本

超文本是电子信息时代特有的一种信息组织方式和接受体验,是相对于传统纸质文本时代的顺序-索引信息结构的巨大变革,业已改变且将继续改变人类社会甚至人类本身。

“Almost no one does just one thing anymore. The screens won't let us. And in an incredible burst of human evolution, our minds have grown accustomed to monitoring multiple inputs at once. Yeah, you're reading this post. But we're nearly three paragraphs in. So if you're anything like me, it's about that time to check Twitter, count the additions to your Google Plus circles, read a handful of new incoming email messages, and chime in on a couple of ongoing instant message conversations. But are we paying less attention to important details?”

标签语言

在WEB应用中,超文本主要由HTML标签语言来表述,这是一个由W3C制定的标准,不过,近期其控制权正逐渐被另一个由浏览器厂商发起的组织WHATWG所掌握1),因此,最新的HTML规范有两份,一份在W3C,一份在WHATWG。。

一个使用HTML描述的文档由若干HTML元素组成,这些元素可能是一段由一对HTML标签修饰的文本,如:

<div>me</div>

也可能只是一个单独的HTML标签,如:

<img src="me.jpg">

每个HTML元素都具备若干属性,每种属性都可以设置特定的值,最后,所有的元素以一种树状的关系相互联系在一起:

  <!DOCTYPE html>
  <html>
    <head>
      <title>Hello HTML</title>
    </head>
    <body>
      <p>Hello World!</p>
    </body>
  </html>

DOM树用于描述HTML文档中各元素的相互关系,上面的HTML文档对应DOM树如下:

document
  + head
    + title
    + style
    + ...
  + body
    + childElementCount
    + chidren
    + ...
  +...

借助于DOM树和脚本语言,为HTML文档引入动态效果成为可能。

锚点

锚点实现了不同HTML文档之间以及同一HTML文档中不同部分的穿梭,彻底颠覆了传统文本的目录和索引机制,是超文本的核心所在。

使用一对HTML的”A”标签可以定义一个锚点元素,也可以称其为一个超链接:

<a href="http://example.com/" target="new">Example</a> 

“href”的值作为超链接的目标,target的值定义了打开超链接的方式,上面的例子表示在名为”new”的窗口打开超链接。

传输协议

使用HTTP协议传输HTML文档是WEB技术的基础,也是WEB技术的核心。

rfc2616定义了HTTP 1.1的大部分内容。这是一个以客户端-服务器(CS)方式运作的请求/响应协议,作为客户端的浏览器向HTTP服务器发送一个请求,HTTP服务器则根据请求的内容和回复一个响应。一般来说,HTTP传输的实现基于可靠的TCP链路。

HTTP请求包括请求行、请求头和消息体三部分,其中,请求行和请求头内都是文本内容,由一个回车符和一个换行符分割;请求头中的各数据域也由回车和换行分割;而请求头和消息体之间则需要一个空行。

请求行格式如下:

GET /example/example.html HTTP/1.1

其中,“GET“为请求方式,其他常见的请求方式还有“POST”、“HEAD”等;“/example/example.html“为请求的资源(含路径)。

请求头的格式为:

name: value (\r\n)
......

其中,name为数据域的名称,value为对应的值。请求头中常见的数据域定义如下:

Host服务器的域名
Accept 客户端支持的内容格式
Accept-Charset客户端支持的字符编码
Accept-Encoding客户端支持的压缩格式
Accept-Language客户端支持的语言
Date请求的发送日期
Range允许请求对象的一部分(以字节记)
Referer如果请求的对象是由某个页面转入的,这个域会给出该页面的地址。
User-Agent对客户端程序的描述
Cookie如果客户端之前访问过同一个服务器且服务器在客户端内写入了特定的数据,这个域内需要包含该数据,以标识该客户端。
Content-Length消息体的字节长度
Content-Type消息体的内容类型
Content-MD5消息体的校验和(BASE54编码)

HTTP响应包括状态行、响应头和数据体三部分,其中,状态行和响应头由文本组成,和HTTP请求一样,为一个回车符和一个换行符分割,响应头中的数据域也由回车和换行分割,响应头和数据体之间则是一个空行。

状态行的格式如下:

HTTP/1.1 200 OK

其中“200 OK“是状态码及其释义。1xx的状态码表示临时相应,2xx的状态码表示成功,3xx的状态码通常用于重定向,4xx的状态码则表示出错,5xx则表示服务器出现问题。

响应头的格式和请求头相同,常见的数据域如下:

Server服务器信息
Date服务器发送数据的日期
Age被请求的对象在缓存中的停留时间
Last-Modified被请求对象的更新日期
Location用于指示重定向的目的地址
Set-Cookie要写给客户端的cookie数据
Transfer-Encoding被请求对象的传输形式
Content-Length数据体的长度
Content-Encoding数据体的压缩方式
Content-Type数据体的内容类型
Content-MD5数据体的校验和(BASE54编码)
Content-Range部分传输中表示数据体的区间
Accept-Ranges数据体区间的表示方式
Connection连接选项:关闭当前连接,下次请求时重新连接,抑或保持当前连接
Expires被请求对象的预计过期时间

作为请求/响应协议,HTTP本身是没有状态的,用户和服务器之间的会话行为需要由应用程序来维持,这就用到了Cookie技术,它允许HTTP服务器将若干对“属性/值”的数据发送给浏览器,而当浏览器再次访问该服务器时需要将这些数据传回。通常,服务器和客户端利用Cookie传递一个Session ID,这个ID在一个客户端首次向服务器发送请求时由服务器产生的,服务器发送HTTP响应时将其附在Cookie中,一定期间内该客户端发送的所有请求时都要把这个ID附在请求头的Cookie中传回服务器,直到长时间无交互导致该会话超时结束。

动态效果

最初,HTML的性质充其量仍旧是一种带有格式标签和超链接的图文混排档,但不久之后,Netscape公司通过在文档中嵌入某种简单的脚本,为HTML增加了响应用户输入事件的功能,从而实现了HTML的动态化。结果,即使某些很简单动态效果都令HTML增色不少:如鼠标悬浮于超链接产生的字体变化等。

Javascript

实现动态效果的脚本语言叫做Javascript,正式名称为ECMAScript,和Java毫无干系。Javascript运行于浏览器的沙盒中,由浏览器引擎负责解释执行。

对于C/C++/Java的程序员来说,Javascript看上去是一种很熟悉的语言,因为其文法几乎完全借鉴于C——包括大小写敏感的变量命名、标识代码块的花括号、几乎所有的运算符以及代码流的控制等——然而仅仅看上去是,Javascript在本质上与C系语言大相径庭,具备许多与C系语言截然不同的特点:

1. 弱类型

Javascript的变量是弱类型的,可以随时定义,定义的时候不需要指定类型,运行的过程中类型可以发生改变,目前支持的类型包括数字、字符串、数组、对象、布尔及未定义。

2. 泛类型的函数

作为实现子程序的一种方式,Javascript的”函数“具备参数传递、支持返回值等基本特征。此外,作为一级类型,一个函数本身就是一个对象,可以作为参数进行传递、可以充当返回值、也可以赋值给变量或对象的属性、还具备自己的属性及方法——对于Javascript来说,函数就是一种特殊的对象,其与其他对象的不同之处在于函数可以被调用执行。

function foo()
{
    if (foo.nickname == "chicken")
        alert("My nick name is chicken");
}
 
function execute(f)
{
    f();
}
var myfoo = foo;
myfoo.nickname = "chicken";
myfoo();
execute(foo);

以上代码中的函数foo将检查其成员nickname是不是“chicken”,如是则弹出警告框。在接下来的代码中,我们使用变量myfoo引用函数foo,为其增加成员nickname并初始化为“chicken”。因此,当我们接下来同样使用变量myfoo调用函数foo时,警告窗会弹出。

Javascript函数不存在函数原型的问题,其参数列表相当随意,几乎没有任何限制,如下面的代码,在调用write函数时,可以给它任意个参数——这是完全正确的语法,只是某些情况下在运行时可能产生不可预测的错误而已(第三个调用会输出“undefined”),而arguments是函数write的成员,write被调用的时候赋值。

function write(info)
{
    document.writeln(info);
    if (write.arguments.length>1) for (i = 1; i < write.arguments.length; i++) document.write(write.arguments[i]);
}
 
write("hello");
write("hello1", "hello2");
write();

调用一个Javascript函数有多种方式,包括没有任何前缀的全局函数方式,对象方法的形式,或构造函数的形式。

当把一个函数赋值给某个对象的成员,然后使用对象去调用函数,该函数就成为了特定对象的方法,可以通过this引用对象本身;而如辅以new关键字调用某个函数的话,就会创建一个新的对象,该函数则扮演着构造函数的角色,通过this引用此新建对象并为其添加成员及进行相应初始化。

function foo()
{
    if (this.nickname == "chicken")
        alert("My nickname is chicken");
}
var f = foo;
f();
 
var obj = new Object();
obj.f = foo;
obj.nickname = "chicken";
obj.f();

以上代码中的函数foo检查其上下文对象的成员nickname是否等于“chicken”,如是,则弹出警告框。在第一次以全局方式调用函数foo时,由于foo没有上下文对象,故不会弹出警告框;而第二次将函数foo赋值给对象的成员f,并且为该对象的nickname赋值为“chicken”,然后以成员方法的形式调用foo时,则有警告框弹出。

下面的代码同样有警告框弹出,这是因为当一个函数以全局全局方式被调用时其上下文对象为window,函数foo的this指向window,同时window会有一个名为foo的属性引用函数foo。因此,以下对函数foo的调用等价于“window.foo();”。

function foo()
{
    if (this.nickname == "chicken")
        alert("My nickname is chicken");
}
var f = foo;
window.nickname = "chicken";
f();
3. 没有类的对象

Javascript是面向对象的语言,但不支持类;它允许使用new操作符依照一个函数作为模板来初始化新建对象,体现了某种构造函数的概念,但对象创建之后仍然可以随意添加成员。以下代码创建了一个名为tom的对象,具备年龄和性别两个属性,分别为35和”male”。

var tom=new Object();
tom.age=35;
tom.gendor="male";

在对象构造过程中,函数体内的this即是对新创建的对象的引用,因此,可以通过this统一定义新建对象的属性和方法。以下代码中,tom和jess都是通过使用employee函数来创建的,所以拥有相同的属性和方法。

function employee(the_age, the_gen)
{
    this.age=the_age;
    this.gendor=the_gen;
    this.swim=function () { 
        document.writeln("I am " + this.age + " years old");
        document.writeln("I cannot swim");
        }
}
var tom=new employee(35, "male");
var jess=new employee(20, "female");
tom.swim();
jess.swim();
4. 基于属性表和原型职责链的运行方式

Javascript的运行核心是一个动态的属性表和原型职责链,如上面所述,属性可以在任何时候添加到对象之中,同时,每个Javascript对象都有一个原型对象,它的属性是可共享的,如果要访问的某一属性当前对象不支持,则会上溯查询原型对象,确认是否支持该属性。这在一定程度上体现了一种继承的概念。多数浏览器支持__proto__属性访问一个对象的原型,但这不是Javascirpt定义的标准方式,理论上讲,原型只是一个对象的内部属性,仅供系统追溯时使用。

利用prototype关键字可以引用并修改构造函数挂接到所建对象上的原型对象。在下面的代码中,由于employee函数参照的原型对象被修改了,因此使用该函数创建的对象tom具备了一个新的方法talk,这个方法其实来自于tom对象的原型对象,即tom.__proto__。需要注意的是,开发者必须明确把握自己所作出的修改,否则,在对象的原型被修改之前对某个新增属性的访问会导致一个无效引用的异常——讨厌而不易检测。

function employee(the_age, the_gen)
{
    this.age=the_age;
    this.gendor=the_gen;
    this.swim=function () { document.writeln("I cannot swim");}
}
var tom=new employee(35, "male");
employee.prototype.talk= function (){ document.writeln("I am talking");};
tom.swim();
tom.talk();

prototype本身是JavaScript函数固有的一个属性,类型为对象,缺省情况下,所有由该函数构建的对象的原型都指向这个对象,JavaScript继承机制则可以通过替换这个对象重构职责链而得以实现。

4. 与HTML文档的交互

Javascript可以通过直接引用对象document来实现与当前加载的HTML文档的交互。

5. 与浏览器的交互

Javascript可以通过引用若干全局对象window来实现与浏览器的交互。所有的浏览器都支持代表浏览器窗口的window对象,window对象提供了一系列可以操作浏览器窗口的方法,如:

  • window.open
  • window.close
  • window.moveTo
  • window.resizeTo

window对象还拥有众多属性,document即是其中之一。此外还包括:

  • screen
  • location
  • history
  • navigator
6. 事件驱动

如果不是被放入页面body部分的话,脚本只有在特定事件的驱动下才会执行,这也是最常见的javascript执行方式。

表单和交互

样式

样式即CSS,可以用于改善HTML页面的布局。

在互联网发展早期,HTML页面的显示控制——如字体、字号、颜色等——都需要直接通过改变对应元素的某项属性来实现,这使得网页的美观受到很大的局限,网页设计也始终停留在匠工水平。样式的出现推动页面设计进入DIV&CSS时代,借助样式,设计师能够从容地对页面的内容进行分类,更加精准地定义内容的格式,并且通过格式重用实现网站的风格化。同时,由于样式控制文件独立于HTML页面,也使得设计师摆脱对前端代码的依赖。

样式的核心在于可以从全局的角度对HTML元素的显示方式进行定义,这种定义可以针对某一种元素,如H1、body、a等,也可以针对某个具体的元素,如id为signature的H1,或某一些元素,如class为content的元素。

样式定义的基本语法为:选择器 {属性:值; 属性:值; …}。其中,选择器可以为页面中的特定HTML元素、或给定id属性某一HTML元素、抑或给定class属性的某些特定HTML元素、抑或三者的关系组合。

li.post {
 font-size: 12px;
}

以上代码规定类属性为post的列表项的字体大小为12px。

li.post .media{
 width: 500px;
}

以上代码规定则类属性为post的列表项内的media类元素宽度为500px。

此处为详尽的选择器规范。

HTML5

CGI及服务器端脚本

LAMP架构

LAMP架构指的是当下广泛应用于WEB站点搭建的以Linux、Apache、MySQL和PHP为核心的软件架构。

Linux

Apache

MySQL

PHP

 
tech/programming/web.txt · Last modified: 2016/10/12 19:59 by admin
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki