《JavaScript设计与开发新思维》——2.5 拼凑一些代码

2.5 拼凑一些代码

利用已经介绍过的一些基础知识,我们继续前进,开始接触JavaScript。当然,我不期望你已经了解JavaScript—这是本书的目的—但是下一个示例阐述了JavaScript的易理解性,并且为第2部分的材料(也即正规训练)提供一些背景知识。

2.5.1 开发基本功能
作为一个简单而实用的例子,我们来创建一个登录表单,然后用JavaScript进行验证。在稍后的章节中,你将学习如何为这个表单应用Ajax,但是在这时添加Ajax可能有点过于复杂。首先创建HTML表单,该表单有3个元素:一个电子邮件地址、一个密码和一个提交按钮。下面是最关键的HTML,存储在login.html文件中(图2.8)。

<form action="login.php" method="post" id="loginForm**">
    <fieldset>
         <legend>Login</legend>
         <div><label for="email">Email Address</label>
<input type="email" name="email"
id="email" required></div>
         <div><label for="password">Password</label>
<input type="password" name="password"
id="password" required></div>
         <div><label for="submit"></label><input type="submit"
value="Login &rarr; " id="submit"></div>
    </fieldset>
</form>
<script src="js/login.js"></script>

为了简单起见,该页面上除了前述的表单之外,什么也没有。该页面还使用了一个基本的CSS文件以添加一些样式;你可以从本书对应网站上下载该文件(CSS文件将在整个可下载脚本的ch02文件夹中)。

上述表单将被提交给login.php。该脚本将进行如下工作:

  • 验证提交的电子邮件地址。
  • 验证提交的密码。
  • 确认提交的值与以前存储在数据库中的相符。
  • 如果匹配,发送一个cookie或者启动一个跟踪用户的会话。
  • 将用户重定向到欢迎页面。

如果你还不知道如何自己实现PHP和MySQL,在以后的章节中,你将看到这个表单的所有实际运行状况。这是基线功能,不管浏览器的JavaScript设置和能力如何,这些功能都有效。如果客户能够加载一个HTML页面,这个系统就很好。下一步是对其进行渐进增强。

2.5.2 添加JavaScript层次
在我们所举的特殊例子中,渐进增强意味着JavaScript将被用于在客户端验证表单数据,仅允许在数据通过时将表单提交给服务器(正如图1.4中的注册示例)。

首先要注意这个表单和没有绑定JavaScript的表单之间的唯一区别—每个元素都有name属性和id属性。name值在表单数据提交到服务器端PHP脚本时使用,而JavaScript将使用id属性值。从逻辑上说,这两个值对于每个元素来说都相同。页面上的每个元素(表单或者其他元素)都必须有唯一的id值。

这个渐进增强的页面还使用了一个外部JavaScript文件login. js。它应该包含在HTML页面中body结束标志之前:

<script src="js/login.js"></script>
现在,至少对于本书的这个阶段来说,这个文件的内容有些复杂。为了理解这个文件当中应该有什么样的JavaScript代码,你必须有事件处理的基本知识。

2.5.3 处理事件
正如第1章中所提到的,JavaScript是一种事件驱动语言,这意味着它仅在事件发生之后进行某些工作。事件的例子包括:

  • 网页加载;
  • 单击一个元素,如按钮或者链接;
  • 在表单元素中输入文本;
  • 将光标移动到一个元素上(也就是mouseover事件);
  • 将光标从一个元素上移开(也就是mouseout事件)。

为了让JavaScript验证一个HTML表单,你必须确定触发验证代码的事件。常用于表单验证的事件如下:

表单提交;
单击提交按钮(这也触发表单提交事件);
改变表单元素的值;
表单元素失去焦点时(不管值是否改变都触发)。
第8章“事件处理”更详细地讨论事件。现在,我们只是在提交的时候验证表单,为此,必须为表单添加一个事件监听器(Event listener)。事件监听器是一个在“这个事件”发生在“这个对象”上时调用的函数。每个对象,不管是整个浏览器窗口还是页面中的具体元素(不管是否为表单元素),都有能够触发的特定事件。被调用的函数通常是你自己定义的。对象、事件类型和函数的组合造成了多种多样的可能性。

为了观察表单的提交事件,我们首先要获得对表单本身的引用。使用 document 对象的 getElement-ById()方法是一种简单而可靠的方式。document对象代表整个HTML内容:从html开始标记到head和body等元素。

Document对象有一个getElementById()方法,它以ID名称为参数,返回对应元素的引用,返回值可以赋值给一个变量供以后使用:

var loginForm = document.getElementById('loginForm');
此时,只要有一个元素(毫无疑问可以是任何类型)的id值为loginForm, loginForm变量将是对该元素的引用。第9章更加详细地研究DOM操纵,但是getElementById()方法非常重要且很容易使用,所以值得在本章里介绍。

有了对表单的引用,就可以用下列代码添加事件监听器:

_element_.on_event _= _function_;
例如:

loginForm.onsubmit = validateForm;
下文的补充说明中将更详细地解释这种语法,但是这一代码行只是说明在loginForm元素遇到一个提交事件时,将调用validate-Form()函数。注意,该函数的名称用在这一赋值语句的右侧,没有引号,结尾也没有圆括号。下面这两种写法都不正确:

loginForm.onsubmit = 'validateForm'; // NO!
loginForm.onsubmit = validateForm(); // NO!

理论上,下一步应该是定义validate-Form()函数,这个函数执行实际的表单验证。遗憾的是,需要先执行另一个步骤。

我将对此加以解释。

从一个服务器请求文档时,客户将按照顺序接受文档的数据。对于HTML页面,这意味着浏览器首先接收DOCTYPE,然后是html开始标记、head标记和head的内容,接着是文件体及其内容,以此类推,直到文档结束。当浏览器遇到对其他必须下载的素材的引用时,就必须相应地进行下载,这些素材包括CSS文件、图像和其他媒体、JavaScript、Flash等。就DOM操纵来说,这一过程很重要,因为浏览器在完全了解HTML 页面(图2.9)之前无法表现DOM。对于JavaScript,这意味着在浏览器加载页面的 HTML 之前,你无法安全地使用 document. getElementById()。

知道何时能够安全地引用DOM元素的最可靠方法是确认浏览器完全加载了整个页面。当然,这是一个事件,可以设置事件监听器,观察事件的发生:

window.onload = init;
提示: 当JavaSript放在靠近文档结尾处时,网站的加载似乎更快,这是因为浏览器在等待JavaScript加载时必须暂停HTML的渲染。

注意: 我打算简化浏览器下载和加载网页的过程,以表达关键的要点。如果你对此过程感到好奇,在网上搜索就能找到很多细节。

对象事件属性

第1章中曾经提到,对象是一个特殊的变量类型,具有预先定义的属性(也就是它自己的内部变量)和方法(即函数)。对象记法(或者圆点)语法用于访问对象的属性和方法。loginForm.onsubmit = validateForm这样的代码将validateForm()函数赋给loginForm对象的onsubmit属性。这似乎有些奇怪,但是这和将数值赋值给一个变量的概念相同: var num = 2; 但在事件监听器的情况下,变量是对象的一个属性,赋给的值是一个函数:稍微复杂一些,但是原理相同。 loginForm对象有一个onsubmit属性,因为loginForm代表一个或者多个触发提交事件的表单元素。这段代码不能用于一个链接,因为链接没有onsubmit属性(但是链接有onclick属性)。引用基于事件的对象属性时,全部使用小写字母:onsubmit而不是onSubmit。 对于上述赋值语句,函数必须与这个事件相关联;因此函数的名称在语句的右侧提供。你不能在函数名称上加引号,这样它将变成一个字符串值而不是函数。你也不能使用functionName()的形式,带上圆括号表示一次实际的函数调用。

这段代码表明,window对象触发加载事件时应该调用init()函数。然后,init()函数可以将事件监听器添加到表单,因为这时进行DOM引用是安全的:

function init() {
    var loginForm = document.getElementById('loginForm');
   loginForm.onsubmit = validateForm;
}

第 7 章“创建函数”介绍自定义函数所必须了解的内容,但是函数的基础知识实际上很简单。首先,使用function关键字,后面跟上函数的名称和圆括号。(init函数的调用很常见,init是Initialize(初始化)的缩写,该函数用于初始化一些必要的JavaScript和浏览器行为。)该函数的实际代码出现在大括号之间,代表着函数调用时将会执行的任务。

作为附加的保护措施,我们在这里添加对象检测,这样表单的事件监听器将仅在浏览器支持document.getElement-ById()的方法下才被添加:

function init() {
     if (document && document.getElementById) {
          var loginForm = document.getElementById('loginForm');
          loginForm.onsubmit = validateForm;
     }
}

现在有两个事件监听器。第一个监听window的load事件,该事件对于每个页面只发生一次,触发时调用init()函数。第二个监听器等待表单的提交,可能发生任意次(也可能一次都不发生)。每当该事件发生时,都调用validateForm()函数。定义该函数是渐进增强的最后一步。

注意: 实际上,浏览器对document对象和getElementById()方法的支持已经超过10年之久,所以对象检测的这种特殊用法实际上并没有必要。

2.5.4 执行验证
validateForm()函数应该验证表单数据并返回表示数据有效性的一个布尔值。如果函数返回true(真),就允许表单提交给服务器端脚本。如果函数返回false(假),那么表单的提交将被阻止。

该函数的外壳如下:

function validateForm() {
}

现在是执行基本验证的时候了,这些验证发生在上述的外壳中。对于电子邮件地址和密码,验证应该检查是否存在某个值(确认电子邮件地址格式有效是可能的,但是需要许多代码)。对于文本输入,可以检查其长度完成简单的验证(也就是证明输入了任意的内容)。这一切从获得每个输入域的引用开始,仍然使用getElementById():

var email = document.getElementById('email');
var password = document.getElementById('password');

提示: 记住,如果网页使用HTML5,而浏览器支持HTML5,将会应用自动化的客户端验证(如前面的插图所示)。

这时,每个变量是对应的表单元素的一个引用。引用变量的value属性就能找到元素的当前值:如email.value和password.value。因为两者都是文本元素,value属性都为一个字符串值,甚至可能是一个空字符串。JavaScript中的所有字符串都有length属性,存储该串中的字符数量。因此,email.value.length是输入到电子邮件输入域的字符数量,然后,可以根据字符数量创建一条简单的条件语句:

if ( (email.value.length > 0) && (password.value.length > 0) ) {
     return true;
} else {
     return false;
}

注意: 检查元素值的长度对于文本输入域是有效的,其他类型的元素以不同的方式验证。

这里使用的是一个简单的验证例程。除非两个表单元素中都输入了一些内容,否则表单就不会提交给服务器端脚本。但是,除了阻止表单提交以外,用户还应该知道错误的发生。可以用更高级的方式提醒用户,但是现在一个警告框可能就足够了(图2.10和图2.11):

if ( (email.value.length > 0) && (password.value.length > 0) )
{
     return true;
} else {
     alert('Please complete the form! ');
     return false;
}

注意: 客户端验证对于最终用户来说很方便,服务器端验证始终是必要的。

你现在有了一个简单、渐进增强、无干扰的JavaScript,在HTML表单发送到服务器之前进行验证。下面的代码块展示了汇总后的所有代码,以及说明关键部分的一些注释。该脚本有三个顶级的(也就是非嵌套的)组件:

validateForm()函数的定义;
init()函数的定义;
将init()函数注册为window.onload事件监听器。
注意: 因为服务器端脚本login.php尚未编写,在表单通过验证时,浏览器试图访问不存在的文件,你将会看到服务器错误。

但是,出于技术性的原因,这3个组件编写的顺序没有关系,我选择以这种顺序编码是因为:

validateForm()在被init()函数引用之前定义。
init()函数在被赋予window.onload属性之前定义。
同样,这种顺序也不是必需的,但是这对于编码的结构有逻辑上的意义。每个函数也以如下代码开始:

'use strict';
使用这一行代码的原因在“引用严格模式”补充说明中加以解释。

// login.js
// Function called when the form is submitted.
// Function validates the form data and returns a Boolean value.
function validateForm() {
    'use strict';
    // Get references to the form elements:
    var email = document.getElementById('email');
    var password = document.getElementById('password');
    // Validate!
    if ( (email.value.length > 0) && (password.value.length >
0) ) {
         return true;
    } else {
         alert('Please complete the form! ');
         return false;
    }
} // End of validateForm() function.
// Function called when the window has been loaded.
// Function needs to add an event listener to the form.
function init() {
    'use strict';
    // Confirm that document.getElementById() can be used:
    if (document && document.getElementById) {
         var loginForm = document.getElementById('loginForm');
         loginForm.onsubmit = validateForm;
    }
} // End of init() function.
// Assign an event listener to the window's load event:
window.onload = init;

引用严格模式

JavaScript自己的严格模式和已经讨论过的浏览器严格模式不同,是在你所写的代码中强制更严格的JavaScript行为的一种方式。严格模式在ECMAScript 5中加入,通过在JavaScript中放置如下字符串引用: 'use strict'; 这一行代码在每个脚本开始可以使用一次,但是正如你在本书中所看到的,用作每个函数的第一行更为可靠。 引用严格模式时,JavaScript将与非严格模式中的执行方式略有不同,一般来说,严格模式将: 导致可能有问题的代码生成错误; 改进安全性和性能; 对将在该语言的未来标准中被删除的代码提出警告。 简而言之,严格模式强制你编写更好的代码,这是一件非常非常好的事情。 如果你希望了解严格模式强制形成的变化细节,可以在网络上搜索,但是在现阶段的学习中对你没有太多意义。

时间: 2024-08-07 02:00:27

《JavaScript设计与开发新思维》——2.5 拼凑一些代码的相关文章

《JavaScript设计与开发新思维》——导读

前言 JavaScript是当今使用最广泛的编程语言之一,可以在几乎所有网页(在所有新的网页)上找到.过去的10年,在经济变化和JavaScript使用方式的扩展之间,越来越多的Web开发人员和设计人员希望了解这种语言.具有讽刺意味的是,在这些事实面前,还有少数人对JavaScript是不是一种真正的编程语言表示怀疑.而且,许多书籍仍然用传统的方式介绍JavaScript,把它当作一种用来实现零散的花招和消遣的技术. 编写本书的目的就是要解决这些问题,以一种容易理解的方式,介绍JavaScrip

《JavaScript设计与开发新思维》——2.2 HTML5入门

2.2 HTML5入门 我写这本书的时候已经临近2012年,HTML5是一个奇妙的东西,它已经以某种形式存在了数年,但是不久之前XHTML2.0停止发展之后,HTML5才成为了Web开发的事实标准.HTML5还没有正式地标准化和发布,这意味着不管何时出现HTML5的最终实现方案,无疑都会与现在讨论的HTML5不同.通常,由于Web浏览器普遍存在而又多变,明智的人应该避开这类新事物.但是你可以采取许多方法,在两个方面上都得到最大的益处:使用一些HTML5特性,而又不破坏用户的体验.我们首先来看一个

《JavaScript设计与开发新思维》——1.6 JavaScript版本和浏览器支持

1.6 JavaScript版本和浏览器支持 我们已经说明过,JavaScript的核心来自于ECMAScript,ECMAScript在2009年推出了最新的第5版.JavaScript的当前版本是基于ECMAScript 5的1.8.5版本,于2010年7月推出.但是在JavaScript中编程时,版本的问题不如"在什么浏览器中可能发生什么情况"那么重要.大部分现代浏览器都支持ECMAScript 3和ECMAScript 5的一部分(ECMAScript 的版本4从未正式发布).

《JavaScript设计与开发新思维》——1.7 JavaScript编程目标

1.7 JavaScript编程目标 开始一次新的尝试时,不管是第一次学习JavaScript还是为了学习更好.更现代的JavaScript技术,都应该设定一些目标.网站的目的当然是为了让客户(使用Web浏览器的最终用户)查看和使用.如果访问者无法使用一个网站,你作为Web开发人员的工作就失败了.朝着这个目标,网站的功能应该在所有浏览器上都能实现,包括移动设备上的浏览器.非可视化浏览器.禁用JavaScript的浏览器和旧的浏览器.完成这一目标比你想象的更容易,这要归功于渐进增强(progres

《JavaScript设计与开发新思维》——2.4 关键的开发方法

2.4 关键的开发方法 在查看代码之前,应该详细地讨论3种开发方法.你选择的方法(可能同时采用不止一种方法)将会影响所编写的代码,更重要的是,影响最终用户的体验. 2.4.1 功能退化 script元素为任何HTML页面添加JavaScript,与此相反的是noscript元素,它用于页面在浏览器不支持JavaScript时提供一个替代信息或者替代内容: <noscript>Your browser does not support JavaScript!</noscript> 如

《JavaScript设计与开发新思维》——1.4 JavaScript和其他常见技术的比较

1.4 JavaScript和其他常见技术的比较 在我开始学习外语之前,从未真正领会英语语法的课程:有时候掌握一种思想只需要一些比较和对照.在接下来的几页当中,我将说明如何将JavaScript与其他你可能已经熟悉的常见技术进行比较,希望你能够更加完整地理解将要掌握的这种语言. HTML和CSS HTML(HyperText Markup Language,超文本标记语言)是用于创建网页的技术.(顺便说一句,如果你还不知道这一点,就需要在进一步学习本书之前学习HTML.)HTML和JavaScr

《JavaScript设计与开发新思维》——2.3 为HTML添加JavaScript

2.3 为HTML添加JavaScript 本章阐述一些现实世界中的JavaScript,这些代码使用的概念将在第2部分中更加正式地学习.但是,这里必须介绍一些基础知识,包括如何将JavaScript代码添加到HTML页面,我怀疑你已经知道怎么做了. 为了在一个HTML页面添加JavaScript,可以使用script元素: <script></script>在较早版本的HTML中,这个标记的type属性是必需的,应该取值为text/javascript,在HTML5中不再需要这么

《JavaScript设计与开发新思维》——1.5 为什么说JavaScript是一种好语言

1.5 为什么说JavaScript是一种好语言 如果你正在阅读这本书,就可能对学习JavaScript有兴趣,但是如果我不表明自己对JavaScript为什么是一种好语言的看法,那就是玩忽职守.最重要和明显的理由是,JavaScript非常有用.在当今网站中常见的大量动态功能都是用JavaScript实现的.实际上,大部分这种功能都是用户所需要的,不使用JavaScript将是一种明显的疏漏.而且JavaScript还能-- 改进网站性能(例如,归功于Ajax).用于修复浏览器缺陷,例如对CS

《JavaScript设计与开发新思维》——第1章 (重新)介绍JavaScript 1.1 什么是JavaScript

第1部分 入门 第1章 (重新)介绍JavaScript 今天的JavaScript是一种被误解的编程语言,从JavaScript所能做到的,到它不能做到的,再到JavaScript不是什么(JavaScript不是Java),关于这种当今Web的核心技术有许多的混淆.不理解一种技术的精髓,就不可能有效地使用它,所以本书的第1章提供对现代JavaScript的一个概要介绍. 本章的大部分篇幅讨论JavaScript的概念,以及它迄今为止的变化历程.接下来,读者将看到有关JavaScript版本以