快意编程:Ext JS Web开发技术详解
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2 Ext JS与AJAX

Ext JS采用XMLHttpRequest对象进行数据的异步交互,使用JavaScript增强用户体验,使用DOM组织内容,使用CSS显示外观,使用XML封装数据。Ext JS采用的技术如图1.9所示。

图1.9 Ext JS采用的技术

下面将对这几种技术进行简要的讲解,以使读者大体上了解这些技术。

1.2.1 XMLHttpRequest技术

从IE浏览器的5.0版本开始,微软公司通过一个名为XMLHTTP的ActiveX对象来实现在不刷新页面的情况下直接与服务器通信的能力,它的出现极大地丰富了浏览器/客户端模式的应用,因此其他浏览器(如Mozilla、Safari等)也实现了类似的对象。

但各个浏览器在实现XMLHttpRequest对象的方式上有很大的区别,比如在IE浏览器中XMLHttpRequest对象的实现方式如下:

var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

而在其他的浏览器中,XMLHttpRequest对象的实现方式如下:

var xmlhttp = new XMLHttpRequest();

所以在创建一个XMLHttpRequest对象时,为了兼容不同的浏览器,开发人员一般采用如下写法:

var xmlhttp;
if (window.XMLHttpRequest) {//判断是否采用new XMLHttpRequest()方式创建
    xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
    try {//如果不是new XMLHttpRequest()对象方式创建,则是IE的方式创建
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) {
      xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
    }
}

在Ext JS中,则采用如下方式创建XMLHttpRequest对象,示意代码如下所示:

var activeX = ['MSXML2.XMLHTTP.3.0',
                      'MSXML2.XMLHTTP',
                      'Microsoft.XMLHTTP'],
var http;
          try {
              http = new XMLHttpRequest();//默认采用new XMLHttpRequest()方式创建
          } catch(e) {
              for (var i = 0; i < activeX.length; ++i) {//数组循环创建,创建成功则跳出循环
                  try {
                    http = new ActiveXObject(activeX[i]);
                    break;
                  } catch(e) {}
              }
          }

在XMLHttpRequest对象创建完毕后,即可采用XMLHttpRequest来发送消息,发送消息有两种方式:一种是异步,另一种是同步。一般情况下,在AJAX中都使用异步方式来与服务器通信。通过XMLHttpRequest对象中open方法的第3个参数,可以用来设定是采用同步还是异步方式,参数为true代表异步,为false代表同步。设定通信的相关参数,即调用open方法,并不代表已经把信息发送给服务器了,只代表这个请求已经建立,要想把信息发送给服务器,还要调用send方法。

在采用异步方式通信时,还需要设定回调函数,以保证系统能够得到服务器端返回的代码,在设置回调函数的时候,一般都要增加两个状态来判断服务器是否处理成功,示例代码如下所示:

//设定回调函数
xmlhttp.onreadystatechange=function(){
    if (4 == xmlhttp.readystate) {//表示服务器端数据已接受成功
      if (200 == xmlhttp.status) {//表示请求成功,服务器端已经处理完成
          //获取返回值
          var txt = xmlhttp.responseText;
          var msg = document.getElementById("msg");
          msg.innerHTML = txt;
      }
    }
}

在Ext JS中,则采用如下方式来和服务器进行交互,示意代码如下所示:

function asyncRequest(method, uri, callback, postData) {
          var o = getConnectionObject() || null;
            //获取创建的XMLHttpRequest对象
          if (o) {
              o.conn.open(method, uri, true);
                //设定文件头
              if (pub.useDefaultXhrHeader) {
                initHeader('X-Requested-With', pub.defaultXhrHeader);
              }
                if(postData && pub.useDefaultHeader && (!pub.headers|| !pub.headers[CONTENTTYPE])){
                  initHeader(CONTENTTYPE, pub.defaultPostHeader);
              }
                //设定回调函数
              handleReadyState(o, callback);
                //发送数据给服务器
              o.conn.send(postData || null);
          }
          return o;
      }
      // 创建XMLHttpRequest对象
      function getConnectionObject() {
          var o;
            //将创建的XMLHttpRequest对象进行计数
          try {
              if (o = createXhrObject(pub.transactionId)) {
                  pub.transactionId++;
              }
          } catch(e) {
          } finally {
              return o;
          }
      }

从上面的代码可以看到,Ext JS大体上也是按照XMLHttpRequest的基本原理来实现AJAX的。

1.2.2 JavaScript(Java脚本语言)

JavaScript是一种动态脚本语言,在真正的面向对象的语言中,例如“C++”或“Java”,有着用于定义“类”的关键字“class”,也有着“private”、“public”等关键字定义属性和方法的私有与公有。在JavaScript中,“类”的实现是直接通过函数实现的。在JavaScript中,使用“function”来构造类。比如:

function User(){           //用户类
    this.name;             //用户的姓名
    this.sex;              //用户的性别
}

函数“User”就定义了一个描述用户对象的类。然后可以用如下代码来创建对象:

var jack = new User();

在JavaScript的类构造函数中,通过“this”关键字向类中添加属性和方法。例如前面给出的“User”类中,使用“var this.name;”来声明一个属性。类中方法的添加与其类似,比如:

function User(){   //用户类
    this.name;      //用户的姓名
    this.login = function(password){//用户的登录方法
      //类的方法
      alert(“我在执行登录操作,密码是:”+password);
    }
}

继承是面向对象语言中扩展已有类型的一种有效途径,JavaScript没有提供用于实现继承的“extends”关键字或者“:”操作符,但是,作为一种动态语言,可以在需要的时候,用“prototype”向类中添加属性和方法。也就是说,JavaScript和一般真正的面向对象语言不同的是,JavaScript只能通过原型来实现模拟的继承,比如:

function ParentClass(){                   //声明一个父类
    this.data = "hutia";                   //声明一个公共属性
}
function SubClass(){                      //声明一个子类
    this.showSubData = function(){         //定义一个公共方法
      alert("公共属性data的值是:"+this.data);
    }
}
SubClass.prototype = new ParentClass();    //使用原型来模拟继承
obj1 = new SubClass();                    //创建一个子类的实例对象
obj1.showSubData();                       //调用子类的公共方法

前面讲的是JavaScript如何实现面向对象的封装,Ext JS中extend(继承)方法的示例代码如下所示:

extend : function(){
          //将o中的值放在作用域中
          var io = function(o){
              for(var m in o){
                  this[m] = o[m];
              }
          };
          var oc = Object.prototype.constructor;
            //返回函数
          return function(sb, sp, overrides){
              if(Ext.isObject(sp)){
                  overrides = sp;
                  sp = sb;
                  sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this, arguments);};
              }
              var F = function(){},
                  sbp,
                  spp = sp.prototype;
              //利用原型函数
              F.prototype = spp;
              sbp = sb.prototype = new F();
              sbp.constructor=sb;
              sb.superclass=spp;
              //利用构造函数
              if(spp.constructor == oc){
                  spp.constructor=sp;
              }
              sb.override = function(o){
                  Ext.override(sb, o);
              };
              sbp.superclass = sbp.supr = (function(){
                  return spp;
              });
              sbp.override = io;
              Ext.override(sb, overrides);
              sb.extend = function(o){Ext.extend(sb, o);};
              return sb;
          };
      }(),

Ext JS中namespace(命名空间)方法的示例代码如下所示:

namespace : function(){
          var o, d;
          Ext.each(arguments, function(v) {
              d = v.split(".");
              o = window[d[0]] = window[d[0]] || {};
              Ext.each(d.slice(1), function(v2){
                  o = o[v2] = o[v2] || {};
              });
          });
          return o;
      },

1.2.3 DOM(文档对象模型)

文档对象模型(DOM)是W3C组织的推荐标准,表示文档和访问、操作构成文档的各种元素的应用程序接口。在JavaScript中,用来获取ID标记元素的方法是:

document.getElementById()

为了方便使用,Ext JS对这个方法进行了封装,实现代码如下所示:

El.get = function(el){
    var ex,
      elm,
      id;
    if(!el){ return null; }
    if (typeof el == "string") { //判断是否为字符串
      if (!(elm = DOC.getElementById(el))) {
          return null;
      }
      if (ex = El.cache[el]) {//判断是否已经放在缓存中了,如果是,就直接取出DOM
          ex.dom = elm;
      } else {//如果没有放在缓存中,就放进去
          ex = El.cache[el] = new El(elm);
      }
      return ex;
    } else if (el.tagName) { // 判断元素的tag名称
      if(!(id = el.id)){
          id = Ext.id(el);
      }
      if(ex = El.cache[id]){
          ex.dom = el;
        }else{
          ex = El.cache[id] = new El(el);
      }
      return ex;
    } else if (el instanceof El) {
      if(el != docEl){
          el.dom = DOC.getElementById(el.id) || el.dom;//通过getElementById方法
          El.cache[el.id] = el; // 进行缓存
      }
      return el;
    } else if(el.isComposite) {
      return el;
    } else if(Ext.isArray(el)) {
      return El.select(el);
    }
    return null;
}

从上面的代码可以看出,Ext JS提供的get方法,其实还是采用了document. getElementById()方法,只不过是对该方法进行了封装。

1.2.4 CSS(样式表)

CSS主要用于控制网页样式并可以将展现样式与网页内容分离。在HTML中有三种使用CSS的方式。

(1)采用<style type="text/css">标记,示例代码如下所示:

<html>
<style type="text/css
<!--
table {font: 12pt }
-->
</style>
<body>

(2)直接在元素内使用CSS样式,示例代码如下所示:

<td style=" font: 12pt >字体大小为12</td>

(3)采用link把样式表引入网页,示例代码如下所示:

<head>
<title>样式示例</title>
<link rel=stylesheet href="../gf.css" type="text/css">
</head>

1.2.5 XML

扩展标记语言(XML)是一种简单的数据存储语言,使用一系列简单的标记描述数据,XML与Access、Oracle和SQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如,数据索引、排序、查找、相关一致性等,XML仅仅是展示数据。XML是从1996年开始有其雏形,并向W3C(全球信息网联盟)提案,而在1998年2月发布为W3C的标准(XML1.0)。XML的前身是SGML(The Standard Generalized Markup Language),是IBM从20世纪60年代就开始发展的GML(Generalized Markup Language)标准化后的名称。一个典型的XML示例如下所示:

<?xml version="1.0" encoding="UTF-8"?>
//引入文件
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
          http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
    <!—有关i18n的配置 -->
    <bean id="messageSource"
        class="org.springframework.context.support. ResourceBundleMessageSource"
        abstract="false" lazy-init="default" autowire="default"
        dependency-check="default">
        <property name="basenames">
            <list>
                <value>com.jl.ui.template.conf.i18n.template</value>
                <value>com.jl.framework.identity.idm.i18n. identityMessage</value>
            </list>
        </property>
    </bean>
    <!—其他的一些依赖bean -->
    <bean id="templateFacade" class="com.jl.ui.template.TemplateFacade">
        <property name="template01Service" ref="template01Service" />
        <property name="template02Service" ref="template02Service" />
        <property name="template03Service" ref="template03Service" />
        <property name="template04Service" ref="template04Service" />
        <property name="template05Service" ref="template05Service" />
        <property name="template06Service" ref="template06Service" />
        <property name="template07Service" ref="template07Service" />
        <property name="template08Service" ref="template08Service" />
        <property name="template09Service" ref="template09Service" />
        <property name="template10Service" ref="template10Service" />
    </bean>
</beans>

可以看到,XML主要是通过一些定义好的标记来表示所要存储的数据,这样程序就可以通过这些标记来读取内容。