JavaScript And Ajax(JavaScript 本质)
ASP.NET 提供了一个基于服务器的富编程模型,这种回传架构能够在服务器端用面向对象程序设计语言完成所有工作。可以确保代码更安全并且能够和所有浏览器兼容。
不过,回传架构也有缺点。页面回传总是带来微小但确实可感觉得到的额外负载,它不能及时响应鼠标移动和按键事件。此外,某些任务(如弹出窗口、提供实时状态信息、框架间通信)需要浏览器的交互,不可能通过服务器端编程完成。
为了解决这些问题,开发人员通常借助客户端编程来弥补服务器端网页代码的不足。通过这些客户端脚本,你可以创建响应更及时的网页并且能够完成某些服务器端不可能完成的任务。
通常,创建富用户界面的自定义控件、为了获得最佳的浏览器兼容性,客户端脚本语言首选 JavaScript。
JavaScript 本质
JavaScript 是一种嵌入式语言,通常嵌入于一个网页,它的代码被下载到客户端计算机并被浏览器解释执行。
JavaScript 一般有两种嵌入方式:
- 把代码直接嵌入到 HTML 元素的事件特性中,这是处理少量代码最直接的方式。
- 添加包含 JavaScript 代码的 <script> 标签,通常可以选择页面加载后自动执行或创建 JavaScript 函数在客户端事件时被调用。
命名的 JavaScript 代码子程序被成为函数,即使它们并不显式的返回值。它们并非被成为方法,因为 JavaScript 语言并不真正支持面向对象编程。
无论是使用 <script> 块还是事件特性或者同时使用两者,都有两种选择去创建 JavaScript 代码,这点很重要:
- 把固定的代码嵌入在 .aspx 页面,一般在 <head> 标签内
- 使用 Page 类提供的方法动态的添加 JS 代码(最灵活)
HTML DOM
服务器端程序员已经习惯了在与之交互时把 Web 页面作为控件对象的集合。客户端程序员则可以按相似的抽象工作。差别在于,现在你使用的每个对象直接映射到一个 HTML 标签,它们不再是任何高级控件,所有的对象被归结为段落、标题、图像、表单控件和表格。
把 Web 页面作为对象树交互的能力源于 HTML DOM(Document Object Model)。JavaScript 和 HTML DOM 的组合被成为 DHTML(Dynamic HTML)。换言之,DHTML 并不是一项独立技术,而是使用 JavaScript 的一种特定方式。
客户端事件
JavaScript 支持一组丰富的客户端事件,如下表:
onchange | 输入控件中修改值时发生。对于文本控件,失去焦点时发生 | select、text、text area |
onclick | 单击时发生 | button、check box、radio、link、area |
onmouseover | 鼠标指针滑过控件时发生 | link、area |
onmouseout | 鼠标指针离开控件时发生 | link、area |
onkeydown | 用户按键时发生 | text、text area |
onkeyup | 用户释放按键时发生 | text、text area |
onselect | 用户选中输入控件的某段文本时发生 | text、text area |
onfocus | 控件获得焦点时发生 | select、text、text area |
onblur | 控件离开焦点时发生 | select、text、text area |
onabort | 用户取消图像下载时发生 | image |
onerror | 图像不能正确下载时发生 | image |
onload | 页面结束下载时发生 | window、location |
onunload | 页面卸载时发生 | window |
如果以 XHTML 编写页面,JavaScript 的名称必须全部使用小写(阅读困难),如果不使用 XHTML 约定,则可以大小写混合,如 onMouseOver。
下面的网页代码为 2 个 TextBox 控件添加 onmouseover 事件:
protected void Page_Load(object sender, EventArgs e)
{
TextBox1.Attributes.Add("onmouseover",
"alert('Your mouse is hoving on TextBox1.');");
TextBox2.Attributes.Add("onmouseover",
"alert('Your mouse is hoving on TextBox2.');");
}
ASP.NET 已经使用了 onchange 事件以支持自动回传功能。如果你加入了 onchange 特性且把 AutoPostBack 设为 true 的话,ASP.NET 会智能的把你的 JavaScript 代码以及 _doPostBack() 函数调用加到了该特性上。你的 js 会先执行,然后是 _doPostBack() 函数。
1. 声明性添加 JavaScript 特性
<asp:TextBox ID="TextBox1" runat="server" onmouseover="alert('Your mouse is hoving on TextBox1.');" />
如果 js 事件名与 C# 事件名相同,这项技术显然不能正常工作。
2. onClientClick 属性
通过增加特性把客户端 js 事件添加到相应的事件处理函数。如果使用的是普通的 HTML 元素,就可以直接设置特性。但如果是 Web 控件,那么可通过 Attributes 集合操纵它们。
不过,ASP.NET 为 js 代码处理单击事件提供了另一种方式,你可以直接设置 onClientClick 属性,该属性在 Button、ImageButton、LinkButton Web 控件里定义。
下面属性在页面回发前显示一个确认消息:
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="return confirm('Post back to the server?')" />
单击按钮仍然能够回传页面并引发服务器端事件。差别在于现在客户端逻辑的 js 代码先发生,然后触发服务器端回传。(返回 false 的话会阻止回传)
脚本块
把大量的 js 代码放在一个特性里是不切实际的。尤其是在几个服务器控件上共用的代码。
一般要插入 <script> 标签内,如下:
<script type="text/javascript">
<!--
window.alert("This window displayed through JavaScript.")
// -->
</script>
HTML 文档注释符号(<!-- 和 -->)向那些不理解脚本的浏览器隐藏脚本内容。此外,符号“//”是由于古老的 Netscape 遇到 HTML 注释结束时会抛出一个 js 解析异常,不过,现代浏览器不会碰到这个问题。
如果你希望这段代码能受控制的被调用,可以将它封装成一个函数:
<script type="text/javascript">
function ShowAlert()
{
window.alert("This window displayed through JavaScript.");
}
</script>
现在你可以关联到某些你想要执行函数的控件的事件上:
<asp:TextBox ID="TextBox1" runat="server" onmouseover="ShowAlert();" />
一个脚本块可以包含任意多个函数。你还可以在其中声明页面级别的变量,它们可以被所有函数访问:
<script type="text/javascript">
var counter = 0;
...
</script>
虽然 js 看起来很象 C#,但它却是一个松散的语言。声明变量和函数时不必指定它的数据类型,函数也不必指定返回值的类型。
如果 js 代码太多而不再能够保持页面的整洁,或者要在多个页面重用一组相同的函数,就有必要把代码转移到另一个文件,不过你还需要创建一个指向外部文件的 <script> 块:
<script type="text/javascript" src="ExternalJavaScript.js">
</script>
.js 文件包含代码,但不必也不能包含 <script> 标签。
将 js 代码转移到外部文件这项技术常用于处理复杂的 js 例程。构建自定义控件时,也可以使用 WebResource 特性把 js 资源嵌入到 DLL 程序集中。
另外,有一点必须要知道!无论是转移 js 代码至外部文件还是嵌入到 DLL 程序集都不能阻止用户检索和检测它。用户可修改网页的本地副本以便使用被篡改后的脚本文件。因此,不要把任何机密算法或敏感信息放到 js 代码里。有时,还需要在服务器端再次执行所有的验证步骤以防用户规避客户端代码。
操纵 HTML 元素
响应事件还只是事情的一半。多数启用了 js 的页面还需要能够改变页面的内容。HTML DOM 简化了这一问题,你所需要做的就是找到元素然后操作它的 innerHTML 属性。
innerHTML 代表 HTML 元素开始与结束标签之间的内容。有些网页使用 innerText 属性,它自动转义 HTML 标签(例如,把 <b> 转换为 <b>),但是,不鼓励使用 innerText,基于 Mozilla 的浏览器(如 Firefox)不支持它。
和服务器端代码不同,js 没有提供用于访问 HTML 元素的成员变量。你需要使用下面语法获得元素:
var element = document.getElementById("txtFirstName");
唯一要确定的是元素必须具有唯一的 ID 特新。
HTML 对象的常用属性:
innerHTML | 开始与结束标签之间 HTML 内容,可包含其他元素 |
style | 返回公开元素所有 CSS 样式属性的 style 对象。可设置元素的颜色、边框、字体和位置 |
value | 指示表单控件的状态。对于文本框表示本文值,对于复选框则表示是否被选中 |
tagName | 返回该对象的 HTML 标签的名字(不含尖括号) |
parentElement | 返回该对象的父级元素 |
调试 JavaScript
VS 增加了整合的 JavaScript 调试。如果使用的是 IE 8 或以上,不需要执行任何步骤来启动客户端调试,无论 IE 如何设置,VS 都会自动对其进行设置。如果是老版本的 IE,需要遵循以下步骤先启用脚本调试:“IE 菜单的工具选项”->“Internet 选项”->“高级”->“浏览组下方”->“取消 禁用脚本调试 的复选框,取消 禁用脚本调试(其他) 的复选框”。
可以在 js 代码中设置一个断点对其进行脚本调试,如下图:
为了实现这个 js 调试,背后有很多神奇的故事。当在 js 里设置断点时,其实是从服务器端的 ASP.NET 页面(.aspx 源文件)里设置的。但是,当浏览器到达断点时,它使用的是呈现的客户端 HTML,它们是有区别的。
如果仔细观察当前 VS 中的调试页面,你会发现其实它是客户端版本。因此,你不会看到 ASP.NET 控件标签,而只会看到它们呈现的 HTML。
使用 VS 的 js 调试功能有一个不错的小技巧。你可以在“监视”窗口里添加一个对 JavaScript 文档对象的引用,然后就可以看到当前 Web 页面的 DOM。这样你可以浏览它的属性、查看它的事件和方法。
监视窗口里显示的当前文档对象的众多属性:
众多事件:
众多方法:
这个调试方法可以汇总 js 的文档对象模型所有的事件和方法。不过各标签元素的成员又各有不同,怎么用,你懂的!