您的位置:首页 > 其它

我学Ajax企业级开发 之 Ajax构建块

2010-10-23 17:32 204 查看
我学Ajax企业级开发 之 Ajax构建块

一、简介
这些内容主要是记录一些我曾经学过的知识,在此记录下做过总结,希望对以后所有帮助。今天学习的是Ajax企业开发第二章。
二、学习内容
2.1 Javascript
2.1.1 JavaScript类型
Javascript的3中原始类型:布尔型、字符串和数值型。
2中特殊的类型:null 和 undefined。
复合类型对象类型:array/function。

2.1.2 闭包
在Javascript中,闭包(closure)也许是最重要和最不容易理解的特性,它也是动态编程语言一种共同的特性。当在一个函数内部声明另一个函数(也叫做内部函数)时,就形成了Javascript的闭包。
当一个函数在另一个函数内部被定义时,内部函数可以访问外部函数定义的任何变量,甚至在外部函数执行完毕后,他仍然可以访问。通过Javascript解析器,外部函数的作用域被动态地附加到内部函数的作用域里。例如:
function Foo() {
var bar = "foobar";
// create the inner function or closure
var showFoobar = function() {
alert(bar);
};
// return a reference to the dynamically created closure
return showFoobar;
}

var myClosure = Foo();
myClosure(); // alerts "foobar"
// or
Foo()(); // alerts "foobar"

2.1.3 面向对象JavaScript
2.1.3.1 公共成员
function Customer(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getFullName = function() {
return this.firstName + " " + this.lastName;
};
}
2.1.3.2 私有成员
function Customer(firstName, lastName) {
var _firstName = firstName;
var _lastName = lastName;
this.getFullName = function() {
return _firstName + " " + _lastName;
};
}
2.1.4 prototype属性
function Customer(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

Customer.prototype.getFullName = function() {
return this.firstName + " " + this.lastName;
}

Javascript中的Function对象包含了一个称为prototype的特殊属性。通过它可以扩展类的定义。这也是Javascript称为一种原型语言的由来。
通过使用prototype属性对类做出的扩展疆会应用到这个类的所有实例,包括任何创建的新实例。在对象初始化之后还可以给它增加字段或者方法,大多数面向对象语言都不支持这种思想,然而,这却让JavaScript更富内涵和更具表现力。
通过一个类的prototype属性定义的字段和方法能够被这个类在任何时刻初始化的实例所访问,其原因是当类通过new关键字创建对象时,在类的prototype属性和这个对象之间创建了一个隐藏的连接。然后当访问这个对象的字段或者方法时,首先会检查自己是否拥有这个字段或者方法。如果没有,就会在对象的prototype属性引用的对象里查找。如果在prototype属性所有引用的对象里面没有找到,它会在这个引用对象的prototype属性里查找,如此递归查询。
2.1.5 面向对象编程和继承
entAjax.extend = function(subClass, baseClass) {
function inheritance() {};
inheritance.prototype = baseClass.prototype;

subClass.prototype = new inheritance();
subClass.baseConstructor = baseClass;
if (baseClass.base) {
baseClass.prototype.base = baseClass.base;
}
subClass.base = baseClass.prototype;
}

function parentClass() {/*class contents here*/}
function subClass(){
subClass.baseConstructor.apply(this, arguments);
}
entAjax.extend(subClass, parentClass);
subClass.prototype.foo = function(args) {
subClass.base.foo.apply(this, arguments);
}
function inheritance() {};
inheritance.prototype = baseClass.prototype;
这个功能通过创建一个空构造函数的临时类(当然,只有一个函数)来完成。接下来women你把这个临时类的prototype属性设置为积累的prototype属性,这种做法意味着除了临时类的构造函数没有代码并且基类的构造函数还没有被调用外,临时类和基类现在是完全一样的。这是一个重要的必要条件,因为基类的构造函数可能会做一些DOM操作,这些操作在类被实例化之前不应该被实际地执行
在临时类创建之后,实例化临时类时类并且把子类的prototype守护星设置为这个临时类的实例,实际上也是基类的实例。
Subclass.prototype = new inheritance();

2.1.6易变性
略.
2.1.7 线程
var i = 0;
function poll(){
alert(i++);
}
window.setInterval(poll,1);
2.1.8 错误处理
JavaScript提供和Java、C#类似的处理方式。try/catch/finally 声明块。在Catch块中,我们可以通过访问错误对象了解到底是什么原因引起了这个错误。通过错误对象暴露出的属性可以访问错误信息(message)、描述(decription)、名称(name)以及数值(number)属性。例如:
try {
var n = Math.random();
if (n > 0.5) throw new Error("n is less than 0.5");
}catch(err){
// Deal with the native error object here
alert(err.message + " ?" + err.name);
}finally{
// Do cleanup here if need be
}

2.1.9 命名空间
if (typeof entAjax == "undefined") {
entAjax = {};
}
命名空间是防止对象、属性、函数或者方法名称互相冲突的一种方式。
2.1.10浏览器类型
var ua = navigator.userAgent;
entAjax.IE = (ua.indexOf("MSIE") > 0?true:false); // Internet Explorer
entAjax.FF = (ua.indexOf("Firefox") > 0?true:false); // Firefox
entAjax.SF = (ua.indexOf("Apple") > 0?true:false); // Safari
2.2DOM
2.2.1 基本原理
2.2.2 操作DOM

2.3CSS
2.4事件
2.4.1 事件流
DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对应有着相当大的影响。这两种事件流分别是捕获(capture)和冒泡(bubble)。
默认情况下,事件使用冒泡事件流,不使用捕获事件流。在冒泡过程中的任意时刻都可以终止事件的冒泡,在遵从W3C标准的浏览器里可以通过调用事件对象上的stoppropagetion()方法来好ixian,在IE里可以通过设置对象cancelBubble属性为true实现。如果不停止传播,事件将一直通过DOM冒泡直接到达文档结点。举个例如如下:
function test(){
alert('你好!');
}
function test1(e){
alert("Hello");
e.cancelBubble = true; //IE中使用
//e.stopPropagation(); //遵从W3C标准的浏览器
}
<div style="border:1px solid #999999; width:500px; height:300px;" onclick="test()">
<input type="button" value="点击" onclick="test1(event)" />
</div>
2.4.2 事件绑定
2.4.2.1 内联事件
<div onclick="nameClicked(event)">John Doe</div>
2.4.2.2 编程式定义事件处理函数
var domFirstName = document.getElementById("firstName");
domFirstName.onclick = function(){}
2.4.2.3 事件注册
var domFirstName = document.getElementById("firstName");
if (entAjax.IE) {
domFirstName.attachEvent("onclick", nameClicked);
} else {
domFirstName.addEventListener("click", nameClicked, false);
}
2.4.3 跨浏览器事件
当以跨浏览器的方式处理事件时存在两个主要的问题。首先,几乎所有的浏览器都遵循W3C DOM的事件的标准来实现他们的市静安模型。IE仍然是个例外。在另一方面,在IE中,this关键字在事件回调方法中引用的却是Javascript执行的上下文,这个上下文可能是一个Javascript对象。
entAjax.EventManager = {};
entAjax.EventManager.attachEvent = function(element, type, callback, setCapture) {
// Browser checking for IE vs W3C compliant browser
if (element.attachEvent) {
// Create two expando properties with function references
element['ntb_' + type] = function() {
callback.call(element);
};
// Attach one of our expando function references to the event
element.attachEvent('on'+type, element['ntb_' + type]);
// Set the capture if it was specified
if (setCapture) element.setCapture(true);
}
else if (element.addEventListener) {
element.addEventListener(type, callback, setCapture);
}
}
2.4.4 事件对象
略。
2.5 客户端/服务器通信
2.5.1 XMLHttpRequet基础知识
var xhr = null;
if (entAjax.IE6) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} else if (entAjax.IE7 || entAjax.FF || entAjax.SF || entAjax.OP) {
xhr = new XMLHttpRequest();
} else {
// no XHR so we are out of luck, maybe degrade and use an IFRAME?
}
xhr.open("GET", "http://www.example.com/myResource", false);
xhr.send(null);
这段代码是定义XHR对象最简单的一种方式。创建XHR对象之后,我们为onreadystatechange事件指定一个回调函数。当XHR对象的eadyState属性改变时,这个回调函数会被触发。最终我们调用XHR对象的open()方法创建一个到服务器连接,open()方法一般有3个参数,分别是:请求类型(GET、Post等等),服务器资源URL,一个指定请求时同步(false)还是异步(true)的标记,除此之外我们还可以为受保护的资源发送一个可选择的用户名和密码。打开之后我们只需要用send(data)方法,这个方法接收任何数据作为唯一的参数,然后将数据发送到服务器,接着请求开始执行。

2.5.1.1 XHR工厂模式
下面有作介绍,此处略。
2.5.1.2 异步请求
为了异步发送请求,我们需要实现两个操作。首先,需要为XHR对象的onreadystatechange属性指定一个事件处理函数,这个函数在XHR对象的readyState属性改变时被触发。其次,我们需要设置传入open()方法的第三个参数为true,告诉XHR对象我们想要发送的是异步请求。
entAjax.HttpRequest = function() {
this.handler = "";
this.async = true;
this.responseType = "xml";
this.httpObj = entAjax.XHRFactory.createXHR();
}

entAjax.HttpRequest.prototype.get = function() {
this.httpObj.open("GET", this.handler, this.async);
this.httpObj.onreadystatechange = entAjax.close(this, this.requestComplete);
if (this.responseType == "xml")
this.httpObj.setRequestHeader("Content-Type","text/xml");
this.httpObj.send(null);
}

entAjax.HttpRequest.prototype.requestComplete = function() {
}

entAjax.HttpRequest.prototype.abort = function() {
this.httpObj.onreadystatechange = function () {};
this.httpObj.abort();
}

var xhr = new entAjax.HttpRequest();
xhr.handler = "http://www.example.com/myResource";
xhr.get();
2.5.1.3 服务器响应
在异步请求环境中设置到onreadystatechange事件的事件的处理函数非常重要,因为这个函数会在请求完成后通知我们,在得到通知后,我们才可以访问来自服务器的的响应。在这个事件处理中,我们也需要执行两个操作。首先,我们要检查XHR对象的readyState属性值。这个属性值是0到4之间的任意值,这5个值分别表名请求未初始化(uninitialized)、正在加载(loading)、加载完毕(loaded)、服务器交互中(interactive)和已完成(complete)。
entAjax.HttpRequest = function() {
this.handler = "";
this.async = true;
this.responseType = "xml";
this.httpObj = entAjax.XHRFactory.createXHR();
this.completeCallback = null;
}

entAjax.HttpRequest.prototype.requestComplete = function() {
if (this.httpObj.readyState == 4) {
if (this.httpObj.status == 200) {
this.completeCallback.call(this, this);
}
}
}

var xhr = new entAjax.HttpRequest();
xhr.async = true;
xhr.handler = "http://www.example.com/myResource";
xhr.completeCallback = showResult;
xhr.get();
2.5.1.4 将数据放松到服务器

entAjax.HttpRequest = function() {
this.handler = "";
this.async = true;
this.responseType = "xml";
this.httpObj = entAjax.XHRFactory.createXHR();
this.completeCallback = null;
this.params = {};
}

entAjax.HttpRequest.prototype.post = function(sData) {
// Either send the provided data or the params
if (sData == null) {
sData = "";
for (var name in this.params) {
sData += escape(name) + "=" + escape(this.params[name]) + "&";
}
sData = sData.substring(0, sData.length-1);
}
// Now send the data using a POST
this.httpObj.open("POST", this.handler, this.async);
this.httpObj.onreadystatechange = entAjax.close(this, this.requestComplete);
if (this.responseType == "xml")
this.httpObj.setRequestHeader("Content-Type","text/xml");
this.httpObj.send(sData);
}

entAjax.HttpRequest.prototype.setParam = function(name, value) {
if (value == null)
delete this.params[name];
else
this.params[name] = value;
}

var myXHR = new entAjax.HttpRequest();
myXHR.setParam("firstName","John");
myXHR.setParam("lastName","Doe");
myXHR.setParam("id","1234");
myXHR.handler = "customers/save";
myXHR.post(); // or myXHR.get(), either way the params get sent back
2.5.2 处理数据
2.5.2.1 XML
var xhr = new entAjax.HttpRequest();
xhr.completeCallback = buildCustomerList;
xhr.handler = "http://www.example.com/myResource";
xhr.get();

function buildCustomerList(xhr) {
var html = "<div>";
// do DOM methods for creating nodes in the web page etc.
var xResponse = xhr.httpObj.responseXML;
var aCustomers = xResponse.getElementsByTagName("Customer");
var len = aCustomers.length;
for (var i=0; i<len; i++) {
customer = aCustomer[i];
html += "<span>" + customer.getElementsByTagName("firstName")[0].text+"</span>";
html += "<span>" + customer.getElementsByTagName("lastName")[0].text+"</span>";
}
return html + "</div>";
}
2.5.2.2 JavaScript对象表示法(JSON)
对格式化数据而言,除了了XML数据格式,另一种流行的选择是使用Javascript对象表示法(JSON),Json是一种数据序列化格式,它使用一种语法来表示基本的数据结构。
对于Javascript而言,Json之所以变得如此流行,是因为攒在双重的原因。首先,可以使用Javascript的eval()函数执行它,把它实例化一个Javascript对象。其次,Json数据,因为它可以跨域传递,所以可以使得人们做到一些更加有趣的事情。
var Customer = eval('({"firstName":"John","lastName":"Doe"})');
alert(Customer.firstName);
2.6 本章中JS所用到的设计模式
2.6.1 单例模式
entAjax.Info = {
ver:"1.0",
status:"active"
};
单例模式(Singlton Pattern):单例模式保证一个类仅有一个实例,并且提供一个访问它的全局访问点。单件在Java中得到了广泛的应用,并且在JavaScript中也可以容易实现。当一个对象需要在整个系统中协调工作时,单件非常有用。某种类型的一个全局变量应用信息就是一个单件的一个例子,这个类包括了版本、状态等信息,这样一个类仅仅需要一个实例。,在Javascript中采用字面量的语法方式处理单件。如上代码所示。

2.6.2 装饰模式
entAjax.Panel = function() {
this.title = "Standard Panel";
}
var myWindow = new entAjax.Panel();
// Make myWindow scrollable
myWindow.scroll = function() { }

装饰模式(Decorator Pattern)允许动态的给对象添加一些额外的行为。装饰围绕原始对象包裹出一个新的对象并给这个对象添加功能,同时,新对象与原始对象的接口必须保持一致。相对于继承来说装饰模式是一种更为灵活的选择,不同点在于继承是在编译期给予子类增加功能而装饰器是在运行期。使用装饰器,你可以给一个单独对象增加功能而保留其他对象不被修改。

2.6.3 工厂模式
entAjax.XHRFactory = {
createXHR: function() {
try {
if (entAjax.IE6) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} else if (entAjax.IE7 || entAjax.FF || entAjax.SF || entAjax.OP) {
xhr = new XMLHttpRequest();
} else {
// no XHR, maybe degrade and use an IFRAME?
throw("XHR not supported in your browser");
}
} catch(e) {
// no XHR object available ?think about degrading
alert(e.message);
}
return xhr;
}
}
var xhr = entAjax.XHRFactory.createXHR();
简单工厂模式是类的创建模式。简单工厂模式是一个工厂决定创建出哪一类产品的实例。

外观模式:在Javascript中一个经常被应用到的设计模式。当为了简化火势为了让调另外一个API变得更加容易而创建一个新的API或者接口时,经常会用到外观模式。在Javascript里我们经常使用这个模式来隐藏跨浏览器开发的复杂性。例如,我们可以使用外观模式简单的调用一个唯一的事件方法,也可以每次都去检查当前的浏览器类型然后再去调用各自的函数,显然,前者要比后者好很多。

对于这些不够理解可以参考其他的专门讲设计模式的书籍如:《JAVA与模式》《大话设计模式》等。

三、总结
这里重新复习了JavaScript的一些知识。如Javascript的数据类型、DOM、CSS、事件XHR等。也介绍了有关设计模式在Javascript中的运用,在这里列出了单例模式、工厂模式、装饰模式。
四、资源下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: