要在你的网页中使用 JavaScript ,你首先必须要知道该将它放在哪儿。其实很简单,只要在你的网页(HTML文件)中插入 <SCRIPT> 和 </SCRIPT> 标记对,你就可以在这两个标记队之间插入你的 JavaScript 代码了: <script>
<script src="mycode.js"></script> 你可以在一个 HTML 文件中使用 <SCRIPT> </SCRIPT> 标记对任意多次。 虽然在通常情况下你都会将所有代码放在 HTML 文件的某一处,但有些时候为了保证你的JavaScript程序能够正确运行,你不得不将它们分散地放在 HTML 文件的多个地方。 不管你是在 HTML 文件中直接插入代码还是通过外部的单独的文件来使用 JavaScript ,通常都是将 <SCRIPT> </SCRIPT> 标记对放在 <HEAD> 和 </HEAD> 标记对之间。这样能够保证在你的网页被下载到客户端后开始执行 JavaScript 的时候你的 JavaScript 代码也已经被下载到客户端了。 这同时也是放置你的 JavaScript 函数的好地方,如果你想要某些代码在你的网页显示出来之后才执行的话,你最好将这些代码放在函数里,等网页显示以后再通过调用函数来执行它们,请看示例。 另外一些时候,你有可能需要将你的脚本代码放在 <BODY> 和 </BODY> 标记对之间。这样做没什么不对的,因为如果你想要通过 JavaScript 代码来生成网页中的 HTML 语句,你就非常需要这样做,请看示例。 <SCRIPT> 标记还可以通过“ LANGUAGE = JavaScript 的版本”语句来指定所要使用的 JavaScript 的版本, “=”号后边的值可以是:"JavaScript"、"JavaScript1.1" 或者 "JavaScript1.2"。大部分的浏览器都会自动识别它所支持的 JavaScript 的版本,而忽略它不支持的 JavaScript 。 你可以针对不同版本的浏览器使用不同的 JavaScript 脚本代码,下边的列表中列出了不同版本的 Netscape 浏览器所支持的不同版本的 JavaScript:
所以对于 Netscape 2.0 浏览器,它将会忽略标记 <SCRIPT LANGUAGE="JavaScript1.2"> 中定义的 JavaScript1.2 版本的脚本代码,但是 Netscape 4.0 将会执行此版本的脚本代码(同时也可以执行前边两个版本的脚本代码)。 你还可以在同一个网页(HTML 文件)中通过 <SCRIPT LANGUAGE="......"> 标记使用不同版本的 JavaScript 代码: <script language="JavaScript"> // 旧版本的 JavaScript 代码。 // JavaScript 1.2 版的代码。 在这个例子里,Netscape 2.0 浏览器将会执行第一个 <SCRIPT>....</SCRIPT> 标志对之间的函数 f1() 而忽略第二个 <SCRIPT>....</SCRIPT> 标志对之间的函数 f1() 。而对于Netscape 4.0 浏览器来说,它将会对两个 f1() 函数都进行处理,因为它支持这两个版本的 JavaScript,但是由于两个函数名字相同,浏览器会自动使用第二个函数 f1() 来覆盖掉第一个函数 f1(),因此执行的结果应该是第二个函数 f1() 的执行结果。 想要了解更多这方面的信息请参考:Netscape's JavaScript Reference. 在你开始编写代码之前,你必须知道一些基本的 JavaScript 语法和结构。 JavaScript 语法与 C/C++、Java 的语法很相似,如果你想要了解非常详尽的语法,可以参考 Netscape's JavaScript Reference 或者 Microsoft's JScript Reference ,在那里你可以看到很多关于 JavaScript 语句、运算符、内建函数等等的内容列表,而我们这里只是讲一些在你开始学习 JavaScript 的时候需要掌握的一些基础语法知识! 【变量】 变量的声明使用关键字 var ,变量名可以是任意长度的字母、数字和下划线组成(“_”),同时变量名第一个字符不能是数字。注意:JavaScript 是对大小写敏感的,也就是说去分大小写,如变量 count 和变量 Count 是两个不同的变量! 在函数外边声明的变量是全局变量,在脚本代码或函数中的任何地方都可以对全局变量进行访问和使用。需要注意的是:在函数外边声明变量的时候,关键字 var 是可选的(即可用可不用,你可以直接给一个没有被声明的变量赋值), 但是如果你在一个函数中想要使用一个局部变量(即变量的有效使用范围只是在函数里边),而且这个变量与函数外边的一个全局变量具有相同的变量名,那么你就必须在函数里边通过 var 来重新声明这个变量,这个变量亦即是一个局部变量。 下边是一些例子: var text; 【字符串】 JavaScript 中使用使用但英文的单引号(')或双引号(")将字符串括起来。如果你想在字符串中使用引号的话,只要在引号前边加上“/”号即可,请看下边示例: var text1 = "Hello world."; JavaScript 大部分的运算符和表达式都和 C/C++、Java 是一样的,例如,下边的语句都是合法: total += 4; JavaScript 大部分的语法也是和 C/C++、 Java 一样的,请看下边列表:
【函数】 使用 function 关键字来定义一个函数: function name(arg1, arg2, ...) {
var w = 5;
在函数中可以使用 return 语句返回一些值,例如: function add(x, y) { 当浏览器下载(Load)一个页面时,任何嵌在网页中的 JavaScript 代码将会在浏览器解释执行网页的时候执行。实际上,JavaScript 代码可能会在图片(images)、背景声音(background sound)或页面的剩余部分下在完成之前执行。 显然,这样可能会发生一些问题。在这个 在线示例 中,我们试图通过 document.linkColor 对象获得用于超文本链接(hypertext links)的颜色,第一次尝试的代码是在 <HEAD>....</HEAD> 标记对之间,第二次尝试是在 <BODY>....</BODY> 标志对之间,下边的是简化后的源代码: <html> // 获得页面超链接的颜色. var lc1 = document.linkColor; </script> <script> // 获得页面超链接的颜色. var lc2 = document.linkColor; // 显示出颜色的 RGB 十六进制值. document.writeln('link color: ' + lc1 + '<br>'); </script> 此例运行的结果如下: link color: #0000ff
对于函数中的代码,只有调用这个函数的时候才会执行,但是你知道应该在什么时候调用函数吗?请看我们的下一个主题:事件。 浏览器可以识别很多的事件,例如“页面下载(Load)完成”这一事件,“用户鼠标移动到超链接或按钮上”这一事件等等。这也就给你提供了一些方便,你可以通过捕捉事件来执行相应的 JavaScript 代码。 一种捕捉事件的方法是定义一个事件句柄,这是针对 HTML 标记对象而言的,不同的 HTML 标记对应不同的对象,不同的这些对象又对应不同的时间句柄 (可以参照下边的表格)。但是并不是所有的浏览器都支持所有相同的事件,我们这里所有例子中使用到的事件都是被 Netscape 和 IE 这两种浏览器所共同支持的。 【定义一个事件句柄】 定义一个事件句柄其实很简单,就是将 事件名称 和 事件触发是要执行的 JavaScript 代码 一同加到 HTML 的标记中去即可,例如: <a href="page2.html" onClick="count++">下一页</a> 在这个例子中,用户每次点击一下“下一页”的超链接,就会触发 onclick 事件,然后在执行跟在 onclick 事件后的 JavaScript 代码:变量 count 增加 1 (count++)。 你可以在事件句柄后边使用任何合法的 JavaScript 脚本代码,如果你想使用多条 JavaScript 语句,那么使用分号(;)将各条语句隔开, 对于调用函数也是一样的。但是有一点要提醒你:在事件句柄后边的字符串中加入 JavaScript 代码的时候一定要注意如何正确使用引号。 【图片的翻滚效果(Rollover)】 看一下这个 在线示例 ,这个例子演示了被人熟知的通过鼠标移动来改变图片(Image)的效果,即图片的翻滚(Rollover),注意:此例无法在 Internet Explorer 3.0 以及更早的版本中正确运行。 <IMG> 标记没有鼠标移动到其上边的事件句柄 onMouseOver,但是超链接标记 <A> 由这个事件句柄,所以我们在 <IMG> 标记两边分别加了标记 <A HREF=...> 和 </A>。 让我们看一下代码先。我们事先编写了一个函数 setImage() 用来改变图片,此函数需要两个参数,name 参数是要改变图片的 <IMG> 标记对象的名字,参数 source 是名字为 name 的 <IMG> 标记对象改变后(不是改变前的)的图片文件名,改变图片的关键在于改变图片对象 <IMG> 的 src 属性: function setImage(name, source) { 下边是对每一个超链接使用了三个事件句柄,一个是鼠标移动到超链接上边是的事件 onMouseOver,一个是鼠标从超链接上边移走的时候触发的事件 onMouseOut,最后一个事件是鼠标点击超链接时触发的 onClick,代码如下: document.images[name].src = source;
<a href="#" onMouseOver 和 onMouseOut 事件都调用了函数 setImage() ,同时传递了参数 name 的值 (这个值在 <IMG> 标记中通过 “NAME= 图片英文名字” 来定义给出) 以及参数source 的值,这个值是我们想要改变后显示的图片的文件名 (包括路径/URL),我们将在后边讲到对象的细节问题,在这里请集中注意力对付事件句柄的相关问题。 注意到 onClick 事件,触发后它只执行 return false 语句,用来告诉浏览器制止/忽略这个事件的默认动作,否则,浏览器将会执行超链接的默认动作,跟随超链接所指向的地址/URL,下载一个新的页面,而通过返回 false 值,我们可以告知浏览器不要这样做。当然,如果你想要让它转到另一个新的页面的话,你可以使用 return true 或者干脆就不要定义 onClick 事件(即删除上边语句中的 onClick 事件)。 【另一个实用的东东】 另一个实用的事件句柄是 onLoad 事件,它用于 <BODY> 标记中。在这里,为了说明这一个事件句柄,我们将以前的一个 在线示例 修改一下,将会得到同样的结果,请看下边代码: <html> An example of using the <b>onLoad</b> event. Use your browser's </font>
下边是 HTML 标记和对应的事件句柄的列表,列表中还附带说明了什么时候会触发相应的事件,如果想详细了解事件句柄,可以参阅 Netscape HTML Reference 和 Microsoft IE Events Reference 。
顾名思义,JavaScript 是居于 Java 程序设计语言而建立起来的脚本语言,两者都是面向对象的 (object-oriented),我们并不想深入探讨面向对象程序设计 (OOP),但是为了你能够更好地了解 JavaScript 语言,我们希望你能够知道一些与对象有关的术语和基本概念。 JavaScript 所处理的每一个对象都是属于一个类 (class) ,类里边定义了组成对象的数据、属性、方法(即是类里边的一些函数)等,使用类可以增加程序代码的复用性,这在一种程序语言中是很重要的,因为这样可以避免重复开发! 你可以将字符串、整数等数据类型看作是一个对象,当你定义一个变量的时候,你就创建了一个对象实例 (通常简称 “对象”),你可以创建很多对象实例,使它们都属于同一个类,也即是相同的对象,比如说,“人”是一个对象(类),而每一个人都是“人”这个对象(类)中的一个对象实例。创建一个对象实例时使用 new 运算符: var text = new String("This is my text.");
一个对象既可以是 core 核心对象 (下边将会提到),又可以是另外一些 JavaScript 的预定义对象 (例如一个图片 Image 对象),甚至可以是你创建的一个全新的对象。 【对象的属性 (Propertie)】 在 JavaScript 中使用英文句号 (.) 来访问对象的属性值: var text = new String("A long time ago...");
然而,有一些属性你是不能直接修改的,例如字符串对象 String 的 length 属性,但是如果你使用 String 对象的 concat() 方法合并两个字符串的话,length 属性也就会自动的改变了,但这种改变是系统自动实现的,而不是你直接通过赋值改变的。 【对象的方法 (Method)】 同样的,对象的方法也是通过英文句号 (.) 来执行的,在方法后边紧跟一对圆括号(),而在圆括号里边包含了使用该方法所需要的参数: var errorMsg = new String("");
JavaScript 包含很多预定义对象,一些是可以用来表示不同的数据类型 (如数字和字符串对象),而另一些是在网页中定义的与 HTML 标记密切相关的对象 (如超链接和图片对象)。 【核心 (Core) 对象】 在 JavaScript 中可供使用的最基本的数据类型被称为核心 (core) 对象,这些对象是:
对于上边给出的对象,你都可以使用 new 操作符创建相应的对象实例,其实你也可以隐含地声明/创建 Boolean、Number 和 String 这几个对象,就像下边那样: var found = false; 【文档中的对象模块】 当页面已经被下载到客户端时,浏览器就会创建几个用来存储页面信息和页面内容的对象。这些对象构成了一个树状结构 (对象的引用也是根据这种树一层一层引用的,引用时使用 “.” 号),在这棵“树”中,最高层的对象是 window 对象,window 对象具有以下的属性:
在这同时,浏览器还会创建另一个高层的对象叫 navigator,这个对象包含了浏览器的类型、版本、安装的插件等等信息。 就像前边说的一样,使用英文的句号 (.) 来引用上边的对象以及对象的属性,例如,要获得当前页面的地址 (URL) 信息,我们可以这样用: var url = window.location.href; 此外,还有一个很方便的东东产生了,那就是浏览器在创建 window 和 navigator 对象的同时,也会将 window 的属性 location、history 和 document 创建为高层对象,所以对于上边的语句,我们还可以简便的写成: var url = location.href; 下边就简单的介绍一下 JavaScript 中为浏览器提供的对象。 【window 对象】 window 对象提供了一些很有用的方法,使用这些方法你可以在浏览器中弹处对话框 (pop-up):
看一下这个 在线示例 就一切都明白了。 我们在调试 JavaScript 脚本代码的时候经常会使用 alert() 方法,你可以将这个函数放在你的代码中,让它显示出所要调试的变量或对象的值,这对于在调试代码时跟踪错误是很重要的。 window 提供的另一些方法是打开、关闭窗口或者改变窗口的显示方式,我们将在第三部分讲到这几个方法的使用。 另外,window 对象中还有一个经常被用到的方法:setTimeout() 方法。此方法可以让 JavaScript 每隔一段间隔时间执行一段代码,代码的执行遵循事件句柄中的规则,也就是说,在这个函数中,每隔一段时间就会执行几条 JavaScript 代码 (每条代码使用“;”隔开) 或者执行调用的函数: setTimeout("count++; alert('Hello world!');", 500); 上边的代码将会每隔半秒钟 (500毫秒) 执行一次 “count++; alert('Hello world')” 代码,此代码包含了两条 JavaScript 语句。也即是说,setTimeout() 方法有两个参数,第一个参数是想要执行的代码或函数 (在此例中是代码:count++; alert('Hello world')),第二个函数是间隔时间,单位是毫秒 (在此例中是500毫秒)。 setTimeout() 方法的返回值是一个唯一的数值,这个数值有什么用呢?如果你想要终止 setTimeout() 方法的执行,那就必须使用 clearTimeout() 方法来终止,而使用这个方法的时候,系统必须知道你到底要终止的是哪一个 setTimeout() 方法 (因为你可能同时调用了好几个 setTimeout() 方法),这样 clearTimeout() 方法就需要一个参数,这个参数就是 setTimeout() 方法的返回值 (数值),用这个数值来唯一确定结束哪一个 setTimeout() 方法: var id = setTimeout("myFunction(arg1, arg2);", 3000); ...其它的 JavaScript 语句... if (error) 需要注意的是,setTimeout() 方法并不会让浏览器暂停执行跟在此方法后的程序代码,浏览器会一直顺着每行代码往下执行,只不过是其它代码只执行一次,而 setTimeout() 方法则是隔一段时间执行一次。在 Netscape 4.0 中,你还可以通过使用 setInterval() 方法重复执行一段代码或函数,相对应的使用 clearInterval() 方法终止前一个方法的执行,这两个方法与 setTimeout() 和 clearTimeout() 方法是一样的,这里就不再多说了。 看一下这个 在线示例 吧,这个例子通过使用 setTimeout() 方法重复的调用一个函数,通过这个函数来获得当前的时间,并将时间显示在页面上,看起来就像是一个正在走的时钟。 【frame 对象】 frame 即是帧,每一个帧对应一个窗口,每一个帧都是由一个 window 对象来指定的,当有一个页面使用了帧设置 (frameset) 的时候,主窗口 (又称为母窗口或母帧) 的 window 对象就包含了一个名为 frames 的数组,这个数组的每一个元素对应一个子帧 (或叫子窗口) ,而每一个子帧都对应一个 window 对象。 那些子窗口/子帧也可以通过使用帧设置 (frameset) 拥有子窗口 (对于最顶层的窗口来说就是孙子窗口了),这样的话它们也就同时拥有了对应于它们的子窗口的数组 frames 。 在某一窗口/帧的页面上使用 window.parent 或者只是 parent 即可指向此窗口的父窗口对象。同理,可以使用 window.parent.parent 指向此窗口的父窗口的父窗口,而使用 window.top 则可以直接指向所有帧中最高层的父窗口。 这样你就可以在这个帧里使用另一个帧里的数据或调用另一个帧里的函数了,详细讲述请参考第三部分。 【document 对象】 document 对象可能将会是你使用的最多的对象之一。此对象包含了与页面内容相关的几个属性,请看:
通常情况下,这些属性对应的是 HTML 标记的属性值,例如 bgColor 属性对应的是 <BODY> 标记中 BGCOLOR="..." 代码中的属性值,你会发现,在其它标记 (像图片和超文本链接) 中也是这样对应的。 images、forms 和 links 属性实际上都是数组,对于数组中的元素,通常会使用像下边的语句那样访问之: var abc = document.images[3]; 这样变量 abc 指向的是网页中的第四个 (因为在 JavaScript 中数租下标是从 0 开始的) <IMG> 标记对应的图片对象,这样用起来其实并不方便,因为如果图片太多,你就必须知道每一个图片在网页中排在第几,要不然就无法知道数组的下标应该是几。不过不用担心, JavaScript 提供了一个方便的方法让你指向图片对象,那就是通过各个图片元素的名字: var abc = document.images["menu"]; 要使用这种方法,你就必须在 <IMG> 标记中加入 NAME= "图片的英文名" 的代码,此例中,<IMG> 标记的代码为:<IMG NAME="menu" SRC="test.gif">,这样你就再也不用担心你要引用的图片对象在网页中的排位顺序了,只要给它取个名字就可以了。 (在 Netscape 3.0 中,这种给图片命名的方法并不好用,可能会的不到正确的结果,这也是 Netscape 3.0 的一个 bug。) 在使用这种方法给网页中的图片对象取名子的时候,千万注意不要有重名的情况,否则就得不到正确结果了。此外,你还可以使用下边的代码一样代替上边的代码: var abc = document.menu; // 这条语句和 var abc = document.images["menu"]; 是等价的 【图片对象 Image】 关于一个图片的信息可以保存在一个叫 Image 的对象中,此对象包含了图片路径 (URL)、图片当前的下载状态、图片的高度和宽度等信息,通常情况下你会将此对象指向在 document.images 数组中存在的图片,也就是放在网页中的图片,但是有时候你可能要处理一些不在网页中的图片对象,这时候 Image 对象就派上用场了。 当你要实现图片翻滚效果的时候,提前将你想要使用的图片下载到客户端是一个很好的想法,因为这样的话,当用户触发事件,要换图片的时候,那个图片已经在客户端了,于是图片就会马上显示出来,避免了时间的延迟,否则换图的时候再让浏览器从服务器上下载图片的话,图片翻滚就有时间延迟了。而使用 Image 对象就可以做到提前下载图片的目的,如下边的代码一样,使用 Image 对象的 src 属性指定图片的路径 (URL),这样就将 images 目录下的图片 pic2.gif 下载到客户端了: var myImg = new Image();
看看改进后的图片翻滚的 在线示例 吧,此程序使用了 Image 对象预先下载图片的方法。注意:此例不能在 Internet Explorer 3.0 或更早的版本中使用,因为它们不支持。 【超链接对象 link】 通常你可能不会想到使用 link对象,如果想知道超链接的地址 (URL),你可以使用 href 属性,如果想知道超链接目标窗口 (window) 或目标帧 (frame),你可以使用 target 属性。 link 对象还包含一个 imagemap 对象,它对应的是 HTML 文件中的 <MAP> 标记。 【表单对象 form】 form 对象自身用的并不是很多,但是 form 对象包含了很多别的元素对象,这些对象组成了表单 form。这些对象包括:文本框对象 (text)、密码框对象 (password)、单选框对象 (radio button)、复选框对象 (check box)、多行文本域 (text area)、隐藏域 (hidden field)、选择列表/下拉列表 (selection list option)、提交按钮 (submit button)、重置按钮 (reset button),它们对应的 HTML 标记可以参照相关的 HTML 语言参考。 这些对象都有共同的属性 name 和 value,value 属性是用户输入的数据或 HTML 文件给定的值,在 HTML 标记中,这两个属性分别对应的代码是 NAME="..." 和 VALUE="...."。 在使用 form 里的那些元素对象之前,首先你必须要引用 form 对象才行,因为 form 对象是那些对象的父对象,而 form 对象前边也要引用它的上一层父对象 document,这种层层引用是很重要的: document.forms[0] // 指向页面中的第一个 form 对象
document.forms[0].elements[3] 通常我们使用表单对象来检查用户的输入是否正确或者用户提交的数据是否正确,这种检查是在表单数据被提交到服务器之前进行的,这样做可以节省用户填表的时间,保证用户只提交一次表单。请看 在线示例 ,此例中演示了如何使用 form 和 form 里边的其它对象来检查用户输入的。 此例中一些需要注意的地方:
我们将在第四部分对表单 (form) 进行更加深入的探讨。 你有时需要打开一个新的浏览器窗口,用来显示信息或广告,但是在这里我要提醒你一下,大部分人在浏览一个网站的时候,是不会注意弹处的新窗口里边写些什么,他们会很快地关掉窗口,只有少数的人会留意这些弹出的窗口。然而,这项技术还是很不错的。 【弹出窗口的小测试】 在这个 在线示例 中,我们给出一个小测试问题的列表,对应于每一个问题都一个显示答案的超链接,而这些超链接将会弹出一个小窗口来显示答案,看一看代码就清楚了。 实际上,每一个答案的超链接都调用了同一个函数 showAnswer(),通过传递的参数 url (此参数是答案所在的页面的地址 URL) 的不同,在弹出的小窗口中显示不同的页面;在这个函数中使用了 window.open() 方法来创建新的窗口: function showAnswer(url) {
新窗口的名字在某些时候可能会用到,在别的窗口中使用 TARGET="新窗口的名字" 使超链接所链接的页面在新窗口中显示,描述窗口特性的参数是一个包含关键字和关键字值的字符串,各个关键字之间使用英文逗号 (,) 隔开,使用这个参数的时候一定要小心,各个关键字、关键字值、逗号之间千万不要有空格。 注意:此例中的 “+” 好只是为了代码能够换行书写才加上的,其实它们只是连结字符串而已,没有别的,不使用 “+” 好一样是可以的。 窗口特性 (即是打开的浏览器的样子) 的关键字、关键字值可以参考下表:
如果在字符串中给定了这些值的话,窗口就会按你定义的现实,否则将会使用默认的值,想要进一步了解这方面的信息请参考 Netscape's JavaScript Guide ! 【给窗口指定页面】 当你使用上面的方法创建了一个新窗口之后,你还可以再次给这个窗口指定新的页面,这就要用到 open() 方法的返回值了,请看下边的代码: myWin = window.open(url, "", "height=100,width=100");
window.opener.location = "newpage.html"; 【关闭一个窗口】 再让我们看一下前边的 在线示例 中我们所打开的新窗口,你会窗口中没有菜单栏,那我们该如何将此窗口关掉呢?不用担心,我们可以使用 window 对象的 close() 方法来关闭打开的小窗口,那个 “关闭窗口!” 按钮中就是使用了此方法: <form>
正如我们在前边的章节中提到的那样,frame 帧其实是单独的窗口,它对应于单独的窗口对象,有自己的 location、history 和 document 属性。 在这个 在线示例 中你将会看到一系列的帧,代码如下: <html> <frameset rows="300,*"> </html> 至于帧的结构、帧是如何分布的等等问题这里就不多讲了,我们希望你能查看一下例子中的源代码,你会发现帧 A 中有一个名为 setFrameColor() 的函数,它的作用是用来改变帧 B、帧 C、帧 D 的背景色,参数 fname 为目标帧的名字,参数 color 为目的背景颜色: function setFrameColor(fname, color) { 正如前边例中所演示的那样,B、C、D 帧的背景颜色确确实实被 document.bgColor 改变了,这里头最重要的是对帧对象的指定,这也是 window.parent.frames[fname] 的作用了,如果参数 fname 的值为 B,则改变帧 B 的颜色。 window.parent.frames[fname].document.bgColor = color;
我们通过当前帧 (帧 A) 的 window.parent 属性指定到顶部的帧 (frameset,此帧包含了A、B、C、D四个帧) ,然后通过顶部帧的 frames 数组加上帧的名字 fname 指定目标帧 (帧 B、C、D),最后通过目标帧的 document.bgColor 属性改变该帧的背景色。 下图很直观地显示了我们上边所讲的帧对象的指定关系:
图 3.1 【引用别的帧/窗口的变量和函数】 你不只是可以引用别的帧/窗口的 document、window 对象,而且还可以访问使用别的帧/窗口的变量和函数。 现在我们将上边的例子修改一下,请看 在线示例 。在新的例子中,我们给下边的三个帧都加了一个按钮,用来恢复各个帧的默认背景色,按下这些按钮后,将会调用帧 A 中的函数 setFrameColor()。下边就是调用帧 A 中 setFrameColor() 函数的代码: window.parent.frames["A"].setFrameColor(window.name, "#ffffff"); 正如你所看到的,我们使用了与前边一样的技巧。首先使用 window.parent 指向顶层的帧 (frameset),然后使用 frames["A"] 指向帧 A,然后在后边加上帧 A 中的函数 setFrameColor(),并且加上两个参数,这样就可以运行帧 A 中的函数了。 需要注意的是函数 setFrameColor() 中使用的类似 window.name 的语句,这个名字和 frames[] 数组中使用的是相同的名字,同时这个名字还是 <FRAME> 标记中通过 NAME="帧的英文名" 设置的名字。 下边是与帧相关的第二个例子的关系图:
图 3.2 类似地,你也可以使用相同的方法使用别的窗口/帧里边的全局变量,只需要将上边例中的函数名改成全局变量名即可。 window 对象的 location 和 history 属性 window对象的 location 属性包含了当前页面的地址 (URL) 信息,你可以直接改变此属性值,将其设置成新的地址 (URL): window.location = "http://www.yahoo.com"; 你还可以通过下边的两种方法中的任何一种来使浏览器从服务器上下载 (Load) 页面:
使用 replace() 方法意味着用户将不能通过按 “返回” 按钮回到前边浏览过的那个页面,但这并不是说用户完全不能回到原来的所有页面,他们只不过是无法回到被 replace() 方法替换的那一个页面 (注意:只是被替换的那一个页面)。 表面上看起来这种方法并不是很有用,而且好像还有点令人讨厌,但是,在一些特殊的情况下这种方法却是很有用的。看看这个 在线示例 就知道了,此例中使用 setTimeout() 方法每个三秒钟就下载一个新的页面,让程序运行一段时间,然后点击浏览器的 “后退” 按钮,你会看到浏览器的历史记录,好多好多,你再试着通过鼠标点击回到开始的页面,怎么样,回去了吗?好像比较麻烦,因为有一大堆的页面在那里挡着。 想要解决这个问题可以使用 replace() 方法,看一下这个改进后的 在线示例 就知道了,新的例子中,你只需点击一次 “后退” 按钮即可以回到最初的页面了。 【history 对象】 history 对象是一个很有用的对象,此对象记录着浏览器所浏览过的每一个页面,这些页面组成了一个历史记录列表。history 对象具有两种方法:
而还有一个 go() 方法也可以控制历史纪录,而且功能更加强大,使用此方法需要一个参数,这个参数值可以是正负整数、零和字符串,例如 history.go(-2) 将是当前页后退两页;如果给定的参数是字符串,那么浏览器就会搜索列表,找到最接近当前页面位置的并且地址 URL 中含有此字符串的页面,然后转到该页面。 请看,下边的两条语句是等价的: history.go(-1);
history.go("netscape"); 在使用这三个方法的时候,如果没有找到符合条件的历史记录的话,将不会发生任何变化,不会改变当前的页面,也不会显示错误。 小技巧:如果在你的网站中有很多页面,那么提供一个 “返回” 功能是很必要的,这样可以方便用户浏览你的网站,但是你并不知道用户是从哪一个页面来到当前页面的,于是你就不能使用 <A HREF="页面的地址">...</A> 的方式来做超链接了,但是可以使用下边的代码来做 “返回” 的超链接: <a href="#" onClick="history.back(); return false;">返回</a> 你可以使用 window 对象的 scroll() 方法使窗口/帧的内容滚动,这种滚动可以是水平方向的也可以是垂直方向的,在这个 在线示例 中,帧里边的美国各个城市天气变化的内容将会不停的滚动。 此例中,当页面滚动到一定的值 (此例中为 750 像素) 的时候,又将页面重新设置成最初的样子 (即坐标值为:(0,0)),这样看起来就是不停的滚动了。可惜的是,并不是所有的浏览器都提供实际的页面高和宽的像素值,所以你要亲自实践一下看看这些值要多大才合适。 你还可以重新书写一个页面中的内容,这就要用到 document 对象的 write() (此方法输出的时候不换行) 和 writeln() (此方法输出完成后自动换行)方法了。这两个方法需要一个字符串参数,这个参数就是要在页面中输出的字符串,可以在字符串中带上HTML代码,那样输出的结果就和其它网页是一样的了,看看这个 在线示例 ,查看一下源代码就知道了。这个例子中是上边的帧通过 writeln() 方法向下边的帧输出内容。 在此例中,你可以试一试输入一些 HTML 代码,看看有什么效果!比如说输入下边的代码: <script>
在函数 rewriteFrame() 中,有如下语句: window.parent.frames["text"].document.writeln(document.forms[0].text.value); 第一条语句是将表单 (form) 的 text 中输入的内容写到下边的帧中,第二行代码是调用 document.close() 的方法告诉浏览器向页面写的操作已经结束。如果你想要是你的输入覆盖掉以前的,那就要使用 document 对象的 close() 方法。 【一个小小的改进】 你可能会注意到上边的例子中,当你点击浏览器的后退按钮的时候,你会看到你的每一次 “提交” 动作都产生了一个新的页面,他们都留在了历史记录中,所以像前边说的一样,你要按很多此 “后退” 才能会回到最初的页面,如果你想除掉这种情况,可以使用 document 对象的 open() 方法,只要在 rewriteFrame() 中加一条语句即可: window.parent.frames["text"].document.open("text/html", "replace"); open() 方法的第一个参数值 "text/html" 是用来告诉浏览器准备接受 HTML 数据,而第二个参数值 "replace" 告诉浏览器不要将新写入的页面加入到浏览器的历史记录列表中,和 location.replace(URL) 是很相似的,功能是一样的,请看改进后的 在线示例 。 在前边的例子中,我们已经接触到很多余表单 form 对象的元素相关 JavaScript 代码,比如按钮、文本输入框等等。form 的元素是为了网页的交互性而设计的,你可以通过 form 获得用户提交的信息,在这章中我们将讨论 form 的元素。 【form 对象】 在我们使用单独的表单 form 对象之前,首先要引用 form 对象。正如我们在第二部分所讲的那样,form 对象由网页中的 <FORM></FORM> 标记对创建,相似的,form 里边的元素也是由 <INPUT> 等标记创建的,他们被存放在数组 elements 中。 在前边我们已经讲过了如何使用 elements 数组了。例如,在一个页面中有两个 form 对象: <html> <form name="customerinfo" action="/cgi-bin/customer.cgi" method="post"> <form name="orderdata" action="/cgi-bin/order.cgi" method="post"> </body> 要使用名为 'quantity' 的元素,可以使用下边三种方法中的任何一种: var e = document.forms["orderdata"].elements[1];
你可以通过元素的 type 属性知道元素是什么类型,在上边的例子中,我们可以使用下边的代码来获得名为 'quantity' 的元素的类型: document.orderdata.quantity.type 结果将会返回 'text'。 【处理一个表单 form】 通常一个 <FORM> 标记中含有 ACTION="...." 的语句,这个语句是用来指定一个表单提交后的服务器端处理文件的文件名 (包括路径,即整个URL),在的一部分中,我们曾经使用过 onSubmit 事件来判断用户的输入是否正确,如果正确就将这些信息提交到服务器进行处理,而服务器上用来处理这些信息的程序所在的文件就是通过 ACTION="..." 来指定的。 如果你想要通过 form 的元素来获得用户的输入,而不在服务器上处理,那就不要在 <FORM> 标记中加入 ACTION="...." 和 METHOD="....",就像我们在在线示例中使用的“查看源代码!”的按钮,这个按钮就是在客户端而不是服务器端运行了一些代码来查看源文件。 【button 按钮对象】 按钮有三种类型,一般的按钮 (button),“提交” (submit) 按钮和 “重置” (reset) 按钮,它们有共同的属性和方法,也有各自不同的属性和方法。这三种按钮可以在 <INPUT> 标记中通过 TYPE="...." 来创建,例如: <input type="submit" value="Submit">
你也可以通过使用 onClick 事件句柄来改变 submit 和 reset 按钮的默认动作。这个 在线示例 中就使用了这三种不同的按钮来完成计算功能。 技巧1:在此例中我们使用了 JavaScript 的内建函数 parseInt(),此函数将文本框里的字符串对象转换成数值对象。否则字符 "2" 和字符 "2" 进行 "+" 运算的结果是 "22",而不是 4。 技巧2:reset 按钮有默认动作,那就是将表单中所有的内容恢复到最初的状态,如果想改变其默认动作,可以像这个 在线示例 那样。 【text (文本框)、password (密码输入框)、hidden (隐藏域) 和 textarea (多行文本框) 对象】 这几个对象都很相似,输入的都是字符串,它们仅仅是显示的方式不一样而已:
技巧:hidden 域是一个很有用的对象,它可以将一些不想在页面上显示的信息传给服务器,但是,虽然这些信息不会显示在页面上,你还是不能将重要的信息,如密码等信息放到此域中,因为用户在客户端是可以通过查看源文件知道这些信息的。 text 和 textarea 元素提供了 onChange 事件,当这些输入框的内容发生变化时就会触发此事件。看看这个 在线示例 就知道了。你会注意到 onChange 事件只是发生在用户离开输入框 (使用了 TAB 键或鼠标焦点离开) 或者按了 “回车” 键的时候发生。 你只有确实地改变了文本框中的内容才会触发此事件。如果你将输入的内容清楚,然后输入完全相同的内容,将不会触发 onChange 事件。 【checkbox (复选框) 和 radio (单选框) 按钮对象】 checkbox 和 radio 按钮可以为用户提供一序列选项,checkbox 用于可以多选的选项中,而 radio 用于只能单选的选项中。 checkbox 对象通过 VALUE="...." 来设置值,但表单提交之后,服务器接收到的只是选中的项的值,此对象有一个 checked 的属性,此属性用来判断每一个复选框的状态,即选中还是没选中,例如:<INPUT TYPE="checkbox" checked> 表示此复选框被选中;而 <INPUT TYPE="checkbox"> 表示此复选框没有被选中。 你可以通过 JavaScript 代码修改、设置 checkbox 的 checked 属性,就像这个 在线示例 中的那样,将 checkbox 的 checked=false 则不选中该复选框,checked=true 则相反。 单选框 radio 按钮与 checkbox 不同,它是在一序列选项中只能选一个,例如,我们对来访用户的年龄进行调查,看他们属于哪一个年龄段,则可以使用下边的代码: <input name="agegroup" type="radio" value="under 21">21岁以下<br>
一个组中的每一个 radio 按钮都代表一个 radio 对象,和 checkbox 类似,每一个都有 checked 和 value 属性,此属性对应于 HTML 标记中的 VALUE="...." 代码,和 checkbox 所不同的是当组里的一个 radio 按钮被选中时,则其它 radio 按钮将不会被选中。 现在问题来了:在一组 radio 按钮中,如何去访问其中的任何一个 radio 按钮?使用 radio 按钮组的名字 (如上边的 agegroup) 是不行的,它的值只是选中的按钮的值,那你要访问其它没有被选中的值该怎么办呢?看看下边的代码就知道了: var rb; R原来使用组的名字 (如 agegroup) 作为数组,然后给数组加上下标即可 (如 agegroup[0] 是访问 agegroup 组中的第一个 radio 按钮)。另外要记住的是在这个数组中,只有一个元素的 checked 属性值是 true,因为任何时候都只有一个 radio 按钮被选中。请看 在线示例 。 for (i = 0; i < document.forms["myform"].agegroup.length; i++) {
【select 和 option 对象】 使用 select 选项列表 (即是通常的下拉列表框之类的) 也是一种给用户提供选项的有用方法,看一下下边的代码: <select name="state" size=1>
注意:IE 3.0 不支持 select 和 option 对象。 select 对象的另外两个常用的属性是 length 和 selectedIndex 属性。length 属性是选项的个数,也就是 options 数组的元素个数;selectedIndex 属性则给出了被用户选中的那个选项在 options 数组中的下标。 下边的代码中,变量 i 是当前用户选中的那个选项在 options 中的下标,而第二行语句通过变量 options[1] 使得变量 s 指向被选中的选项对应的那个 option 对象: var i = document.forms["myForm"].state.selectedIndex;
为了处理多选的情况,你可以使用 option 对象的 selected 属性通过循环检测每一个 option 对象,就像这个 在线示例 演示的那样,查看一下源代码就知道它是如何实现的了。 【创建和删除 option 对象】 注意:IE 4.0 对选择列表 selection 和 option 的方法不同于 Netscape,这一部分内容只能运用在 Netscape 3.0 或者更高版本。 你还可以通过代码创建和删除选项 option 对象。创建 option 对象使用 Option 数据结构,例如: var opt = new Option(text, value, defaultSelected, selected) 参数 text 是显示在页面上的选项的文字,参数 value 对应于 <OPTION> 标记中的 VALUE="...." 属性,即 option 对象的值;参数 defaultSelected 和 selected 是布尔值,用来设置此新建的 option 对象是否为默认选项,以及是否被选中,这两个参数都是可选的,即可以不提供这两个参数的参数值。这个 option 对象可以被加入到一个 options 数组中。而删除一个已经存在的 option 对象,只需将此对象在数组中的那个元素设置为空 ('null' 值) 即可,同时,这样也使数组变小了。 这个 在线示例 演示了如何创建一个两层的菜单系统,而且此菜单系统的第二层菜单是根据第一层菜单动态生成的。注意,这个例子不能在 IE 浏览器中使用。 此例中一些值得注意的地方:
在这一章中,我们将大致的学习一下一些 JavaScript 中比较高级的话题,在此我们只是通过一些例子大致学习,而不进行深入探讨。 正如您所看到的,JavaScript 提供了很多网页组件和数据的对象及对象类型。但是,您的目光不能仅仅限于这些,您可以根据自己的需要创建自己的对象、属性和方法,这是很有用的,比如说您需要一个比较复杂的数据结构的时候,您就需要这样做。 在创建一个新的对象之前,您首先要创建一个数据结构。这些工作都在一个函数里边处理,在该函数中定义您的对象的属性(可以给这些属性设置初始值),然后你就可以创建居于此对象的方法了。 【构造对象函数】 每一个对象都需要一个构造对象函数,我们通过使用 new 关键字调用此函数来创建一个新的对象实例。这类函数定义了对象的属性,同时给这些属性设置初始值。您还可以在此类函数中声明对象的方法。 下边就是使用构造对象函数的一个例子,在这个函数中定义了一个新的对象 Product,此对象定义了每一个产品的基本属性: function Product(name, num, price, shipping, quantity) { 注意关键字 this,它指向被创建的对象。您可以像下边那样创建新的 Product 对象实例: this.name = name;
var item1 = new Product("blender", "9003-2", 24.95, 2.50, 2);
var total = (item1.price + item1.shippingCost) * item1.quantity;
上边的例子中通过访问 Product 对象 item1 的 price、shippingCost 和 quantity 属性计算 item1 的总价值,如果我们需要经常计算总价值,那么像上边那样用起来就很不方便,不过不用担心,我们可以为计算总价值创建一个方法,很简单,只要在构造对象函数中添加一行代码:“this.totalCost = totalCost;”,然后在构造对象函数的后边定义一个名为 totalCost 的函数: function Product(name, num, price, shipping, quantity) { 注意在构造对象函数中定义该对象方法的格式:this.methodName = functionName,这里的方法名和函数名并不需要使用相同的名字,我们这里是为了看得清楚才使用相同的名字 totalCost 的。现在我们就可以使用此对象的方法了: this.name = name; function totalCost() { return ((this.price + this.shippingCost) * this.quantity);
var total = item1.totalCost(); 如果想了解如何构建和使用自定义对象,可以看一下这个 在线示例 ,这个例子中定义了一个简单的购物车,我们构建的对象名为 ShoppingCart,同时还给这个对象定义了增加和删除产品项的方法。 使用 cookie,您可以将一些数据信息保存在客户端用户的机器中,而在以后用户浏览您的网页的时候再调出来使用。通常我们使用 cookie 保存一些数据、登陆帐号等。 创建一个 cookie 需要用到下边的信息:
通常,您只需要设置前两项 "cookie 的名字=cookie 的值" 和 "结束时间" 即可。在设置结束时间的时候,您可以使用 Date 对象,但要注意格式,单位是毫秒。下边就是一个例子,在这个例子中,"结束时间" 被设置成从当前时间算起过任意多天 (此例设置的 "结束时间" 是 7 天后): var days = 7;
【经常用到的 cookie 函数】 为了让您有个好的开始,下边的三个函数分别提供了设置、删除、获取 cookie 的功能: function setCookie (name, value, expires) { escape() 和 unescape() 是 JavaScript 的内建函数,它们用来将一些特殊字符转换成十六进制代码。通常情况下,cookie 中的名字、值都不能包含任何空格、逗号或分号。使用这两个函数可以将这一类的字符转换成合法的可供 cookie 使用的十六进制字符。 document.cookie = name + "=" + escape(value) + function getCookie(name) { var search; search = name + "=" function deleteCookie(name) { var expdate = new Date();
删除所有您不再使用的 cookie 是一个很好的习惯,因为客户端会限制您可以存储的 cookie 个数 (对于 Netscape 浏览器来说:每一个主机/域最多是 20 个 cookie,总共可以存储 300 个)。上边的删除 cookie 的函数将 cookie 的结束时间设置成前一天的时间,这样就可以达到删除的目的了。 看看这个 在线示例 就知道上边函数的用法了。 注意:以下的部分使用 JavaScript 1.2 ,而且只运用于 Netscape 和 IE version 4.0 或者更高版本。 我们在这个教程中已经学过了事件句柄 (event handler),Internet Explorer 浏览器几乎为每一个 HTML 标记提供了事件句柄,而 Netscape 却有所不同,虽然它也为很多 HTML 标记提供了事件句柄,但是一些事件必须通过别的方法来捕捉。 【在 Netscape 中捕捉事件】 在 Netscape 4 或者更高版本的浏览器中,你可以捕捉当前浏览窗口中 window、layer 或 document 级别的对象的事件。captureEvent() 方法可以完成此操作, 此方法指定想要捕捉的事件,然后在通过编写函数来处理此事件句柄。 下边的例子中我们通知 window 对象捕捉鼠标点击的事件: window.captureEvents(Event.CLICK); function myClick(even) {
如果想捕捉更多的事件,您必须使用逻辑或运算符“|”来分割各个事件类型,如下边的代码所示: window.captureEvents(Event.MOUSEDOWN | Event.KEYDOWN);
【Internet Explorer 中的事件】 在 Internet Explorer 中不需要传递 event 对象,因为通常的时间对象都是 window 对象的一个属性。不幸的是,IE 的这些属性和 Netscape 的却不尽相同。 【编写具有兼容性的代码】 幸运的是,这两种浏览器之间还是有共同的代码可以使用的,最重要的是能够使用代码将两种浏览器区分开来。你可以尝试使用一些对象来试探浏览器的类型,例如,你可以使用 document.layers 对象来试探,这个对象是 Netscape 支持的对象,而相对应的 document.all 对象则是只有 IE 才支持的对象, Netscape 则不支持: if (document.layers) { 如果所试探的对象不存在 (即当前的浏览器不支持),它的值为空 (null) ,这就促使 if 表达式的值为“假” (false)。这种方法也可以用来防止这两种浏览器不支持该对象的老版本试图执行这些代码。 // 在此处编写 Netscape 支持的代码 else if (document.all) { // 在此处编写 IE 支持的代码 else { // 在此处编写 Netscape 和 IE 都支持的代码
看一下这个 在线示例 将会对您又很大的帮助。例子中的代码可以在 Netscape 和 IE 两种浏览器中实现相同的效果。 正则表达式是用于模式匹配的,它提供了强大的字符串替换、转换以及搜索功能。 Netscape 和 IE 在正则表达式对象的使用上有细微的不同,但是下边的代码却是通用的: var myRE = /匹配模式/标记; 匹配模式的过程被看成是逐字匹配的,同时使用正则表达式还能匹配特殊字符或特殊格式的字符串 (左边的符号是匹配模式中使用的特殊格式):
由于 '*' 是特殊字符,它的作用是匹配零个或零个以上的 '*' 前边的字符,所以如果想匹配字符 '*',需要在此字符前加一个反斜杠 '/' 字符。因此 '/*' 是匹配一个字符 '*'。你可以到 Netscape's JavaScript Reference 中去看一下有关正则表达式的细节。 标记可以是下边的值:
test() 方法用来比较已知的字符串,如果匹配则返回“真”值 (true)。可以看一下这个 在线示例,在这个例子中,使用了正则表达式来判断用户的输入是否符合电子邮件 (Email) 地址的格式:userid@domain.net。 动态 HTML (Dynamic HTML 或 DHTML) 给 HTML 增加了几个新的标记,同时也增加了几个 JavaScript 的对象。动态 HTML 的一个主要特性是充分利用网页中的层 (layer) 和位置 (position)。 在这里我们再次声明,Netscape 和 IE 在应用上是有所不同的,Netscape 增加了支持“级联样式单” (Cascading Style Sheets 或 CCS) 的 <LAYER> 标记用来定位网页中的元素,而 IE 却支持更多的样式单,这些样式单都是居于 World Wide Web 联盟标准的 (可以参见第六部分的 DHTML 相关链接)。 【给页面的内容定位】 虽然 Netscape 对 CSS 的支持比较有限,但是我们还是可以很容易地使用 <LAYER> 标记来创建被定位的内容。下边的代码在两种浏览器中可以产生相同的效果: Netscape IE 显示的文本。 <layer bgcolor="#ffffcc" left=150 top=200 width=200 height=20>
<div style="background-color:#ffffcc position:absolute;
为了让代码在两种浏览器中都能实现相同的效果,我们可以使用前边讲过的方法首先探测一下浏览器的类型,然后再分别使用 document.writeln() 输出适用于两种浏览器的代码参见 在线示例 。 【文档对象模型DOM】 现在我们已经可以给网页中的内容定位了,但我们怎样才能熟练巧妙地使用这种方法使它成为 DHTML 技术的一部分呢?“文档对象模型” (简称 DOM) 是一个很流行的名字,它指的是在网页中的 JavaScript 分级对象。DHTML 为层与样式单增加了一些新的对象,你可以像使用 JavaScript 中其它对象那样使用这些对象。 当然,Netscape 和 IE 在 DOM 上的应用也有所不同,但是我们还是可以像上边的例子那样使用相应的代码来实现相同的效果。 你可以将一个内容块从一个地方移动 (重新定位) 到另一个地方,可以让它从看得见变成看不见。为了实现这些目的,你要针对不同的浏览器正确地处理好 JavaScript 对象。 让我们重新写一下上边的代码,并且在代码中给内容块加上名字,这样我们才能在程序代码中引用这些内容块作为对象来使用 (这其实就是 DOM 的一部分): Netscape IE <layer name="block1" bgcolor="#ffffcc" left=150 top=200 width=200 height=20>
<div id="block1" style="background-color:#ffffcc position:absolute; 现在我们将内容块放在 JavaScript 函数中当作对象来使用,同时返回此内容块对象本身: function getBlock(name) { 正如你所看到的,Netscape 使用 document.layers 数组来存储块对象,而 IE 则是创建名为 document.all.块名字.style 的对象来表示块。上边的函数返回了块对象,于是我们就可以使用这个返回值来访问块的属性或执行块的方法了。 // For Netscape. if (document.layers) // For IE. else if (document.all) { // 以上都不是,则返回 null. else
现在让我们来看一下 在线示例 是如何移动一个块的。对于 Netscape 来说,我们只要设置块对象的 left 和 top 属性的值就可以达到移动块的目的,在 IE 中则是使用 pixelLeft 和 pixelTop 属性。在下边的函数 moveBlockBy 中将会改变这些属性的值: function moveBlockBy(x, y) { var block = getBlock("block1"); if (document.layers) { 参数 x 和 y 是块在水平和垂直方向上的移动增量。 【处理浏览器的兼容性问题】 正如你所看到的,两种浏览器在 DOM 上的运用也有很多不同之处,这样就给你在网页中实现 动态 HTML 效果带来了挑战,所以在编写代码的时候应该尽量避免使用不兼容的属性、方法等。 当然,你也可以只设计谋一种浏览器的代码,例如只设计 IE 浏览器可执行的代码,而不考虑 Netscape,但是这样你就将会失去 Netscape 的用户群。或者你也可以设计多套网页或网站,让它们分别支持各种浏览器,但是这样将会给维护网页或网站带来很大的麻烦,增加复杂性。 |
JavaScript教程
最新推荐文章于 2024-09-20 11:38:47 发布