[04 Web] Javascript Lab -- 客户端脚本的设计和应用 Lab 设计者:严强(javas)
Javascript客户端编程

  在”Javascript基本概念“中,我介绍了Javascript核心语法的基础知识,在本章我将接着上一章讲述如何用Javascript操纵浏览器提供的页面对象。浏览器提供的对象主要是指DOM(文档)对象树。在现代浏览器中,页面中每个的元素都被映射为这颗DOM树的某个节点。我们可以在响应事件(EVENT)之后通过Javascript增加、删除、修改节点或者节点的属性来改变页面元素的显示,由此来实现所谓的动态页面(DHTML)。

  在Web技术发展的早期,浏览器所能提供的编程接口相当有限,通过脚本我们只能操纵Web页面中很少的一些元素,比较典型的有表单(FORM)和层(LAYER)。后来随着DOM对象模型提出,W3C的标准的陆续出台,大大促进Web客户端技术的发展。目前脚本可以操控的范围基本上已经扩展到浏览器中所有可能出现的元素。可是由于标准提出滞后于业界产品的推出,加上各家浏览器生产商对标准的理解不同,由此造就了各家浏览器提供的接口互不兼容,激烈竞争的历史时期。客户端段技术发展至今,已经基本上到了以IE为主流,标准逐渐被实现的阶段。

  正是由于历史原因,导致了Javascript的客户端编程带有了很大一部分经验因素,不同浏览器之间的兼容性问题成为了主要问题之一。在随后的具体内容中,对于具体元素具体属性等细节问题基本上不会提起。至于DOM的架构和EVENT对象,韩老师的课上一定会提起,所以此处只给出结构图,略去说明。重点将会放在如何访问对象和事件处理映射上。

 

一、浏览器DOM模型


  1、DOM0文档模型


   window

    |-- screen

    |-- history

    |-- location

    |-- navigator

    |-- document

    |-- frames ------ --> window

 

  document

    |-- anchors

    |-- applets

    |-- embeds

    |-- forms

    |-- frames

    |-- images

    |-- links

    |-- scripts

    |-- body

 

  document

    |--form

      |-- elements

      |-- button

      |-- checkbox

      |-- fileUpload

      |-- hidden

      |-- option

      |-- password

      |-- radio

      |-- select

      |-- submit

      |-- text

      |-- textarea

 

  DOM0虽然不是W3C提出的正式标准,但是所有的主流浏览器都支持DOM0模型,所以实际上它才是真正的标准。

 

  2、IE-NAV实现的DOM模型


  IE —— Internet Explorer  NAV —— Netscape Navigator

  IE实现的每一级Document元素中都含有一个 all 的集合变量。

  用”基本概念“ 中ARRAY节中介绍的关联数组的方法可以通过 元素名.all[成员名] 访问任何深度的成员属性或方法。

 

  NAV没有像IE一样的 all 集合属性。

  NAV中曾经在NAV4中,document有过一个Layers的集合变量,但似乎在NAV7中已经被废弃了。

  访问NAV6以上浏览器中页面元素主要通过 getElementById(元素Id)或者是下面将介绍的常用元素访问方法。

 

  3、常用对象访问方法


  document

    |-- form :id = myForm

      |-- text :id = myTextField

 

  对于FORM中的Id为myTextField的文本框,我们可以通过以下几类方法访问它:

  方法一:全路径:document.myForm.myTextField,在Form元素范围内绝对通用。

  方法二:数组法:document.forms[ 0 ].text[ 0 ],如果可以确定具体的索引值(0 表示第一个),可以不用 Id 找到元素。

  方法三:导航法:IE4+:document.all[ "myTextField" ] 或 document.all.myTextField 或 document.getElementById( "myTextField" )

          NAV6+: document.getElementById( "myTextField" )

 

  以上三种即为常用的对象访问方法,都很好用,但使用起来不太方便。实际上如果我们把每个需要访问的元素都加上 Id 之后,问题就会变得简单多了,详情请见 ”Javascript样例“ 中对 MM_findObj 的解释。

 

二、浏览器EVENT模型


  1、IE-NAV实现的EVENT模型


  在IE中Event是一个全局变量(window的一个属性)。在事件处理器中我们可以通过 window.Event 来访问事件信息。

  

  Window

    |-- Event :IE

      |-- altKey

      |-- button

      |-- cancelBubble

      |-- clientX

      |-- clientY

      |-- ctrlKey

      |-- fromElement

      |-- keyCode

      |-- offsetX

      |-- offsetY

      |-- returnValue

      |-- screenX

      |-- screenY

      |-- shiftKey

      |-- srcElement

      |-- toElement

      |-- type

      |-- x

      |-- y

 

  在 NAV 中 Event 是通过参数传递给处理程序的。

  处理程序的格式为 function handle ( event ) { ... }

  NAV4有很独特的Event结构,但是年代久远,这里不多提了。

  而NAV6+似乎采用的是DOM标准Event结构和NAV4的Event结构的混合体。

 

  Event :DOM

    |-- altKey

    |-- bubbles

    |-- button

    |-- cancelable

    |-- clientX

    |-- clientY

    |-- ctrlKey

    |-- currentTarget

    |-- detail

    |-- eventPhase

    |-- metaKey

    |-- relatedTarget

    |-- screenX

    |-- screenY

    |-- shiftKey

    |-- target

    |-- timeStamp

    |-- type

    |-- view

 

  Event :NAV4

    |-- height

    |-- layerX

    |-- layerY

    |-- modifiers

    |-- pageX

    |-- pageY

    |-- screenX

    |-- screenY

    |-- target

    |-- type

    |-- which

    |-- width

    |-- x

    |-- y

 

  2、事件处理映射的方法


  事件处理映射指的是建立事件处理程序与事件之间关联的过程。通常有三种方法:

 

  方法一:URL法:把脚本放在URL可以出现的位置。

  该方法通常用于处理 <a> 标签的单击事件。

  

  <a href = "Javascript: alert('Hi !');" >Click Me </a>

  Click Me

 

  方法二:事件属性法:把脚本放在 onXXX(事件属性名)的属性值中。

  该方法几乎可以处理任何有事件属性的元素。

 

  <a href = "#" onclick = "Javascript: alert('Hello !');return false;">Click Me Too</a>

  Click Me Too

 

  方法三:事件属性法:在脚本中为相应对象的 onXXX 属性赋值。

  该方法几乎可以处理任何有事件属性的元素,而且可以动态处理事件,不同时期更换不同处理函数,把null赋给onXXX属性相当于取消对相应事件的处理。

  如果把 <script> 标签中的内容移到外部文件 *.js 中,那么我们就可以把 HTML 文件中的脚本痕迹降到最低,只剩下 Id 和 <script> 引入标记。

  但由于与标签分离,this 指针的指向会有所差异,要实现传参也比较麻烦。

 

  <script language="javascript" type="text/javascript">
  <!--//--><![CDATA[//><!--
    function initHandle(){
      var arc = getObj("mark");
      arc.onclick = function(e) {
        if(!e) e = window.event;
        alert("e.screenX = " + e.screenX + " : e.screenY = " + e.screenY);
        return false;
      };
    }
    window.onload = initHandle;
  //--><!]]>
  </script>

  ...

  <a href = "javascript:void 0;" id="mark">Click Me Again and Again !</a>

  Click Me Again and Again !

 

  3、有关THIS指针


  在不同的代码段中使用THIS指针的会有不同的含义。

 

  ...

  window.varb = "pp";    // 等价于 this.varb = "pp";

  function Point ( x, y ) {

    this.x = x;

    this.y = y;

    alert( this );
    alert( this.varb );
    alert( this.document );

  }

  var newPoint = new Point ( 1, 2 ) ;  // 式一

  Point ( 1, 2 ) ;           // 式二

  ...

  <a href = "javascript: void 0;" onclick = "Point(1, 3); return false;">Click me -- onXXX </a>   <!-- 式三 -->
  <a href = "javascript: Point(1, 3);">Click me -- URL </a>                  <!-- 式四 -->
  <a href = "javascript: void 0;" onclick = "alert( this );alert( this.varb );alert( this.document ); return false;">Click me -- alertTHIS </a>  <!-- 式五 -->

  

  式一中,this指向新建对象 newPoint 。

  式二中,this指向浏览器的顶级对象 window。

  式三中,this指向浏览器的顶级对象 window。

  式四中,this指向浏览器的顶级对象 window 。

  式五中,this指向 <a> 标签代表的对象。

 

复旦大学软件学院 《Web应用基础》课程 2005年3月 版权所有