12.2 事件驱动与事件处理

来源:互联网 发布:jd2017c.123js.cn 编辑:程序博客网 时间:2024/05/16 00:50

12.2  事件驱动与事件处理

事件驱动是JavaScript响应用户操作的一种处理方式,而事件处理是JavaScript响应用户操作所调用的程序代码。

12.2.1  事件驱动

在多年以前,计算机程序通常是以批处理的模式运行。所谓批处理,就是开发者事先写好一些代码,再将这些代码一次运行。这种处理方式有点类似于通过HTML代码直接编写的网页。浏览器只是将HTML代码逐行解析,并显示在浏览器窗口。

后来,在批处理模式中,开发者可以加入一些特定的代码,在程序批处理期间,可以停下来等待用户输入一些信息,并根据用户输入的信息来判断和执行某个程序分支,这就使程序有了初步的交互性。

随着鼠标、触摸屏等设备的出现,批处理时代就逐渐远去,取而代之的是事件驱动的时代。当然,批处理也还能使用,只是使用的范围和频率比事件驱动要少得多。以鼠标为例,在事件驱动中,用户可以使用鼠标单击等方式进行操作,程序则根据鼠标指针的位置以及单击的方式进行响应。JavaScript使用的就是这种事件驱动的程序设计方式。

在JavaScript中,事件(Even)包括以下两个方面:

  ●     用户在浏览器中产生的操作是事件,如单击鼠标、按下键盘上的键等。

  ●     文档本身产生的事件,如文档加载完毕、卸载文档等,都是事件。

12.2.2  事件处理

在JavaScript中,浏览器会使用事件来通知JavaScript程序响应用户的操作。事件的类型有很多种,如鼠标事件、键盘事件、加载与卸载事件、得到焦点与失去焦点事件等。在事件产生的时候,浏览器会调用一个JavaScript程序来响应这个事件,这就是JavaScript的事件处理方式。要想让浏览器可以调用合适的JavaScript程序,就必须要做到以下         3点:

(1)设置HTML文档中响应事件的元素。在一个HTML文档中,并非所有元素都会去响应事件。就鼠标单击事件而言,一般在HTML文档的正文不会响应该事件,但在按钮中一般都会响应该事件。

(2)设置元素响应事件的类型。在确定了哪些元素响应事件之后,要设置该元素响应事件的类型。例如,一个按钮通常会响应鼠标单击事件(click事件),而一个下拉列表框通常会响应选项变化事件(change事件)。在同一个元素中,也可以响应多个事件。例如,一个超链接,在鼠标移动到该超链接上时,可以响应鼠标移动到对象上事件(mouseover事件),当鼠标从超链接上移开时,又可以响应鼠标移开事件(mouseout事件)。

(3)设置响应事件的程序。为了让浏览器可以响应事件,必须要设置响应事件的程序。例如一个按钮被单击时,浏览器会响应这个click事件,此时浏览器就会在JavaScript中寻找一个合适的程序,并运行该程序。这个程序可以是用户自定义的函数,也可以是一段JavaScript代码,还可以是JavaScript内置对象的方法等。

12.2.3  在HTML标签中设置事件驱动

在JavaScript中,可以响应的事件有很多,如鼠标单击的click事件、鼠标双击的dblclick事件、鼠标移动的mousemove事件、按下键盘按键的keypress事件等。而在一个HTML文档中可能会有很多元素,如按钮、下拉列表框、复选框等。那么如何设置哪个元素响应哪种事件,如果设置响应事件时应调用什么JavaScript程序呢?

要设置元素响应什么事件,就必须在标签中添加一个与事件相关的属性,属性名为“on”加上事件名。例如,要让一个图片响应鼠标单击事件,就要在该图片的<img>标签中添加一个onclick属性,如果要让该图片响应鼠标移动事件,就要在该图片的<img>标签中添加一个onmousemove属性。要设置在响应事件时调用的程序,只需在属性值中输入函数名即可。如代码清单12-4所示,请注意加粗的文字。

代码清单12-4  在HTML标签中设置事件驱动

<html>

    <head>

        <title>在HTML标签中设置事件驱动</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

    </head>

    <body>

        <img src="img/img01.JPG" onclick="alert('您单击了图片')">

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample04.htm”的内容,其运行结果如            图12-7所示。在本例中单击图片时,会触发click事件,浏览器会调用alert()方法来响应该事件。

图12-7  sample04.htm的运行结果

12.2.4  在JavaScript代码中设置事件驱动

从12.2.3小节中可以看出,设置事件驱动事实上就是为元素添加了一个属性,响应事件的程序实际上就是该属性的值。通过BOM,可以很方便地在JavaScript代码中设置元素响应的事件。请看代码清单12-5,注意加粗的文字。

代码清单12-5  在JavaScript代码中设置事件驱动

<html>

    <head>

        <title>在JavaScript代码中设置事件驱动</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

    </head>

    <body>

        <form name="myForm">

            <input type="button" name="myButton" value="按钮">

        </form>

    </body>

    <script type="text/javascript" language="javascript">

        <!--

            function clickButton()

            {

                alert("您单击了按钮");

            }

            myForm.myButton.onclick = clickButton;

        -->

        </script>

</html>

上述代码为光盘目录里“代码/第12章/sample05.htm”的内容。在本例中,创建了一个按钮,单击该按钮时会调用clickButton()函数,并弹出一个警告框。本例的关键代码        如下:

myForm.myButton.onclick = clickButton;

这是一个典型的BOM对象引用方式,myForm代表表单,myButton代表表单中的按钮,onclick是该按钮的属性。需要注意的是,onclick属性值为“clickButton”,而不是“clickButton()”。如果为“clickButton()”,则会直接执行clickButton()函数,而不会将clickButton()函数赋值给onclick属性。

12.2.5  事件处理

当浏览器获得用户产生的事件时,则会自动调用一段JavaScript程序来处理这个事件。调用JavaScript程序的方法有3种:直接调用内置对象的方法或内置函数、调用用户自定义的函数、直接调用JavaScript语句。

12.2.5.1  调用内置对象的方法或内置函数

调用内置对象的方法或内置函数来处理事件,这是一种比较简单的处理方式。只有在处理事件的语句比较简单,并且只需要使用内置对象的方法或内置函数就能完成处理过程的情况下,才使用这种方法。其具体的使用方法如代码清单12-6,请注意加粗的文字。

代码清单12-6  调用内置对象的方法

<html>

    <head>

        <title>调用内置对象的方法</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

    </head>

    <body>

        <input type="button" value="按钮" onclick="alert('您单击了按钮')">

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample06.htm”的内容。在本例中创建了一个按钮,当单击该按钮时,会调用alert()方法,弹出一个警告框,如图12-8所示。在本例中,直接将Window对象的alert()方法赋值给onclick属性,这是直接调用内置对象方法的事件处理方式。

图12-8  sample06.htm的运行结果

12.2.5.2  直接调用JavaScript代码

除了可以在事件中直接调用内置对象的方法或内置函数之外,还可以直接将JavaScript代码写在HTML的标签中。在产生事件时,浏览器会直接调用这些JavaScript代码并运行。其具体的使用方法如代码清单12-7所示,请注意加粗的文字。

代码清单12-7  直接调用JavaScript代码

<html>

    <head>

        <title>直接调用JavaScript代码</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

    </head>

    <body>

        <form name="myForm">

            <input type="text" name="numberA" size="2">

            +<input type="text" name="numberB" size="2">=

            <input type="text" name="numberSum" size="4">

            <input type="button" value="计算" onclick="var mySum=0;mySum=

            parseInt(myForm.numberA.value)+parseInt(myForm.numberB.value);

            myForm.numberSum.value=mySum">

        </form>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample07.htm”的内容。在本例中。创建了3个文本框和1个按钮。在第1个和第2个文本框中输入数字之后单击“计算”按钮,第3个文本框中会自动显示第1个和第3个文本框中的数字之和,如图12-9所示。

图12-9  sample07.htm的运行结果

在本例中,onclick属性后的代码就是一段JavaScript代码,语句之间使用分号作为分隔符。单击按钮时,JavaScript会自动运行这些JavaScript语句。只有在处理事件的语句比较简单时,才使用这种方式。

12.2.5.3  调用用户函数

以上两种调用JavaScript代码的方式都比较简单,如果要实现比较复杂的程序处理,可以使用调用用户函数的方式。将处理事件的程序放在一个函数中,再通过事件来调用该函数。这样,可以实现更强大的功能。请看代码清单12-8,注意加粗的文字。

代码清单12-8  调用用户函数

<html>

    <head>

        <title>调用用户函数</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

        <script type="text/javascript" language="javascript">

        <!--

            function mySum()

            {

                var mySum=0;

                var numberA = Number(myForm.numberA.value);

                var numberB = Number(myForm.numberB.value);

                if (isNaN(numberA))

                {

                    alert("第1个文本框中输入的不是数字");

                }

                else if (isNaN(numberB))

                {

                    alert("第2个文本框中输入的不是数字");

                }

                else

                {

                    myForm.numberSum.value=numberA+numberB;

                }

            }

        -->

        </script>

    </head>

    <body>

        <form name="myForm">

            <input type="text" name="numberA" size="2">

            +<input type="text" name="numberB" size="2">=

            <input type="text" name="numberSum" size="4">

            <input type="button" value="计算" onclick="mySum()">

        </form>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample08.htm”的内容。从本例中可以看出,调用用户函数可以现实更强大的功能,并且源代码看起来也比较直观。

12.2.6  在超链接中使用click事件

在JavaScript中,可以响应的事件有很多种,如单击事件、双击事件等。这些事件也都可以作用在大多HTML元素之上,例如单击事件可以产生在按钮、图片、单选框、复选框中,也可以产生在超链接中。在默认情况下,单击超链接时,浏览器将加载<a>标签的href属性值所指向的URL。但如果在超链接中设置了onclick属性,单击超链接时,会响应click事件吗?

12.2.6.1  在超链接中使用click事件

由于超链接的特殊性,在单击超链接时,可以产生两种状态:一种是响应click事件,另一种是跳转到href属性值所指定的URL上。如果在超链接上同时拥有href属性和       onclick属性,那会发生什么情况?请看代码清单12-9,注意加粗的文字。

代码清单12-9  在超链接中使用事件

<html>

    <head>

        <title>在超链接中使用事件</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

    </head>

    <body>

        <a href="sample01.htm" onclick="alert('您单击了超链接')">本章中的第一

        个范例</a>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample09.htm”的内容。在本例中,既设置了<a>标签的href属性,又设置了<a>标签的onclick属性。对于这种情况,JavaScript会先响应onclick属性值中所设置的事件处理程序,再将网页跳转到href属性值中所设置的URL上。因此,在本例中,单击超链接时,先弹出一个警告框,如图12-10所示。只有在单击了图12-10中的【确定】按钮之后,才会执行网页跳转程序。

图12-10  sample09.htm的运行结果

12.2.6.2  click事件的处理代码为跳转网页的语句

虽然大多数浏览器在12.2.6.1小节的这种超链接中,当存在onclick属性时,都会先响应click事件后跳转网页,但是有一种情况,并不是所有浏览器都会严格地按这种方式进行处理。请看代码清单12-10,注意加粗的文字。

代码清单12-10  在超链接中使用事件

<html>

    <head>

        <title>在超链接中使用事件</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

    </head>

    <body>

        <a href="sample01.htm" onclick="location.href='sample02.htm'">本

        章中的第一个范例</a>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample10.htm”的内容。在本例中,onclick属性值中的“location.href='sample02.htm'”语句使用了BOM中Location对象的href属性,该语句的作用是在当前浏览器窗口中加载sample02.htm文件。按照前面的结论,JavaScript应该会先响应click事件,再将网页跳转到href属性所指定的URL中。因此,JavaScript可能会有两种不同的处理结果:

  ●     先响应click事件,加载sample02.htm文件。由于已经加载了sample02.htm,当前文件(sample10.htm)已经不存在,因此,不再加载sample01.htm文件。

  ●     先响应click事件,加载sample02.htm文件。加载完sample02.htm文件之后,再加载sample01.htm文件。

可是在事实运用中并非如此。在IE浏览器和Opera浏览器中,并不会执行onclick属性值中的跳转语句,而会直接加载sample01.htm文件。而在Firefox浏览器和Netscape浏览器中,会先加载sample02.htm文件,再加载sample01.htm文件。因此,在这两个浏览器中,必须要单击两次“后退”按钮,才能从sample01.htm文件后退到sample10.htm文件上。读者可以自行运行该文件查看效果。

12.2.6.3  将click事件处理语句写在href属性值中

在动态网页中,常常需要在单击超链接时处理一些数据,而不是跳转一个网页。在这种情况下,通常有以下三种处理方式:

  ●     不设置<a>标签的href属性,只设置onclick属性。在这种处理方式下,通常超链接文本会和正文的文本以相同的形式出现,即不会有默认的下划线。当鼠标放在超链接上也不会显示小手的形状(除非为该超链接设置了CSS)。因此,用户很难知道这是一个可以点击的超链接。

  ●     将<a>标签的href属性值设置为“#”,并设置onclick属性。在这种处理方式下,用户可以很明显地看出哪些文字是超链接。在单击该超链接时,也可以执行onclick属性值中的JavaScript语句,并且不会跳转网页。但是,由于href的属性值为“#”,浏览器会自动跳转到当前网页的顶部。如果当前网页内容比较多,浏览器窗口出现下拉滚动条时,可以很明显地看到跳转,而这种跳转往往不是网页设计者的          本意。

  ●     在没有为<a>标签设置onclick属性时,如果单击了该超链接,浏览器会加载href属性中的URL。如果href属性值并不是一个URL,而是一个JavaScript语句的话,那么浏览器就会执行该语句。因此,可以直接将JavaScript语句写在<a>标签的href属性值中,让href属性代替onclick属性。在这种处理方式下,既可以响应click事件,又可以不让网页跳转。

在<a>标签的href属性值中添加JavaScript语句之前,必须要先使用“javascript:”语句来声明href属性值中的语句为JavaScript语句。否则,浏览器会将href属性值中的JavaScript语句当成是URL进行加载。请看代码清单12-11,注意加粗的文字。

代码清单12-11  在超链接中使用事件

<html>

    <head>

        <title>在超链接中使用事件</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

        <script type="text/javascript" language="javascript">

        <!--

            //多添加几个换行,让效果明显

            for (var i=0;i<100;i++)

            {

                document.write("<br>");

            }

        -->

        </script>

    </head>

    <body>

        <a onclick="alert('您单击了第二个超链接')">第1个超链接</a><br>

        <a href="#" onclick="alert('您单击了第二个超链接')">第2个超链接</a>

        <br>

        <a href="javascript:alert('您单击了第三个超链接')">第3个超链接</a>

        <br>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample11.htm”的内容,其运行结果如图12-11所示。

图12-11  sample11.htm的运行结果

在本例中创建了3个超链接,这3个超链接的处理方式如下所示:

  ●     第1个超链接中,没有设置href属性,因此,从图12-11中看起来好像只是一行文字,并且鼠标放在上面的时候,也不会显示小手的形状。因此,很难让用户知道这是一个可以点击的超链接。但是如果用户单击了该超链接,会弹出一个警告框,而且单击警告框中的【确定】按钮之后,不会跳转到任何URL上。

  ●     第2个超链接中,href属性值为“#”,如果单击该超链接,先会执行onclick属性值中的JavaScript,弹出一个警告框。在单击警告框中的【确定】按钮之后,浏览器会自动跳转到当前网页的顶部。

  ●     第3个超链接中,直接将JavaScript语句写在href属性值中。在单击该超链接时,可以执行href属性值中的JavaScript语句,而且不会有任何跳转。

读者可以自己运行该文件查看效果。

12.2.7  事件的返回值

事件的返回值通常是由事件处理程序提供,但JavaScript中并不要求所有的事件都有返回值。如果事件处理程序没有返回值,浏览器会以默认的情况来进行处理。不过,开发者可以通过事件的返回值来判断事件处理程序是否正确处理了程序。在这种情况下,事件的返回值通常是布尔值。如果事件的返回值为true,则浏览器会采取默认的操作,如果事件的返回值为false,则浏览器会阻止默认的操作。

以提交表单为例,当用户单击提交按钮时,浏览器会将表单内容提交到<form>标签的action属性值所指定的URL上,这是浏览器所默认的操作。在用户单击提交按钮时,将会激发submit事件。如果submit事件返回false,则浏览器会阻止默认的操作,即不提交表单数据。请看代码清单12-12,注意加粗的文字。

代码清单12-12  事件的返回值

<html>

    <head>

        <title>事件的返回值</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

        <script type="text/javascript" language="javascript">

        <!--

            function checkDate()

            {

                if (myForm.myName.value=="")

                {

                    alert("请输入姓名");

                }

                else if (myForm.myPassword1.value=="")

                {

                    alert("请输入密码");

                }

                else if (myForm.myPassword2.value=="")

                {

                    alert("请重复密码");

                }

                else if (myForm.myPassword1.value!=myForm.myPassword2.value)

                {

                    alert("两次密码输入不一致,请重新输入");

                }

                else

                {

                    return true;

                }

                return false;

            }

        -->

        </script>

    </head>

    <body>

        <form name="myForm" action="submit.htm" onsubmit="return

        checkDate()">

            姓&nbsp;&nbsp;&nbsp;&nbsp;名:<input type="text" name="myName">

            <br>

            密&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="password" name=

            "myPassword1"><br>

            重复密码:<input type="password" name="myPassword2"><br>

            <input type="submit" value="注册">

        </form>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample12.htm”的内容。本例的关键知识点如下所示:

(1)创建了一个文本框、两个密码框和一个提交按钮。

(2)当单击提交按钮时,会激发submit事件。以下代码说明当激发submit事件时,调用checkDate()函数来处理该事件。

<form name="myForm" action="submit.htm" onsubmit="return checkDate()">

(3)注意以上代码,onsubmit属性值为“return checkDate()”,这说明要从checkDate()函数中获得返回值。

(4)如果checkDate()的返回值为false,则阻止提交操作。否则,将数据提交到submit. htm网页中。其运行结果如图12-12所示。

在本例中,如果<form>标签的代码如下所示,则在单击提交按钮时,虽然会执行checkDate()函数中的语句,但是在执行完该函数中的语句之后,无论结果如何,都会执行默认的操作,即将数据提交到submit.htm网页中。这是因为没有使用return语句获得事件的返回值。

<form name="myForm" action="submit.htm" onsubmit="checkDate()">

图12-12  sample12.htm的运行结果

12.2.8  this运算符与参数传递

this运算符所代表的是“自身”,通常用于代表激发事件的元素本身。this运算符常在事件中使用,可以用来传递参数。请看代码清单12-13,注意加粗的文字。

代码清单12-13  this运算符与参数传递

<html>

    <head>

        <title>this运算符与参数传递</title>

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

        <script type="text/javascript" language="javascript">

        <!--

            function checkName(obj)

            {

                if (obj.value=="")

                {

                    alert("请输入姓名");

                }

            }

            function checkPassword(password)

            {

                if (password=="")

                {

                    alert("请输入密码");

                }

            }

        -->

        </script>

    </head>

    <body>

        <form name="myForm" action="submit.htm">

            姓名:<input type="text" name="myName" onblur="checkName

            (this)"><br>

            密码:<input type="password" name="myPassword" onblur=

            "checkPassword(this.value)"><br>

            <input type="submit" value="提交">

        </form>

    </body>

</html>

上述代码为光盘目录里“代码/第12章/sample13.htm”的内容。本例的关键知识点如下所示:

(1)定义了一个checkName()函数,该函数的参数为一个对象。在该函数中,使用以下语句判断参数的value属性值是否为空。如果为空,则弹出一个警告框。

if (obj.value=="")

(2)使用以下语句创建了一个名为myName的文本框。其中,onblur属性说明当文本框失去焦点时,调用checkName()函数。在以下代码中,chentName(this)中的“this”,就是代表文本框自身,即myName这个控件对象自身。因此,以下代码是将整个文本框对象传递给checkName()函数。

<input type="text" name="myName" onblur="checkName(this)">

%注意:在文本框中单击鼠标,可以让文本框得到焦点。所谓“得到焦点”,就是让文本框中得到输入文字的状态,此时可以在文本框中输入文字。而在文本框之外的任何一处单击鼠标,都可以让文本框失去焦点。所谓“失去焦点”,就是让文本框失去输入文字的状态,此时不能在文本框中输入文字。

(3)定义了一个checkPassword()函数,该函数的参数为一个数值。在该函数中,使用以下语句来判断参数是否为空。如果为空,则弹出一个警告框。如图12-13所示。

if (password=="")

图12-13  sample13.htm的运行结果

(4)使用以下语句创建了一个名为myPassword的文本框。其中,onblur属性说明当文本框失去焦点时,调用checkPassword()函数。在以下代码中,checkPassword(this.value)中的“this”,就是代表文本框自身,而this.value代表的是文本框中的文字。在以下代码中,传递给checkPassword()函数的是文本框的值。

<input type="password" name="myPassword" onblur="checkPassword(this.

value)">