《Ext JS权威指南》——2.7节Ext JS 4语法

2.7 Ext JS 4语法
1.配置对象
Ext JS的基本语法就是使用树状的配置对象来定义界面,其格式如下:

{
      config_options1:value1,
    config_options1:value2,
    …
     config_optionsn:valuen,
    layout:{},
    items:[
    {},//配置对象
    {}//配置对象
    …
  ],
    listeners:{
    //定义事件(根据需要而定)
        click:function(){},
        dblclick:function(){}
        …
    }
}

格式中从config_options1、config_options2到config_optionsn都是API文档中对象的配置项(config options)。很多初学者会错误地认为API不全,找不到配置项。事实上API是完整的,只是有些布局隐含了面板或其他部件,但都在同一配置对象内定义。例如在使用Accordion布局的时候,想消除布局标题栏右边的小图标,需要使用hideCollapseTool属性,而该属性是在Panel对象里的。在这方面,Ext JS 4的API已经做了调整了,增加了一个其他配置项(Other Configs)的列表。
属性layout可以是对象,也可以是字符。该属性表示在当前容器内使用什么布局来填充子控件。如果没有特殊要求,直接使用布局的别名作为值,例如,2.3节的示例中Viewport使用了Fit布局来放置子控件。如果有特殊要求,则要使用对象来定义该值。例如,如果使用Hbox布局,布局内的子控件需要居中对齐,则定义如下:

layout:{
    type:'hbox',
    align:'middle'
}

属性items是一个数组,可以在里面定义当前控件的子控件,里面可以是1个或多个配置项,根据你的需要而定。例如2.3节的示例,在Viewport下使用了一个Panel面板作为其面板。属性listeners是一个对象,可以在里面绑定事件,对象的属性就是事件名称,属性值就是要执行的函数。
2.关于xtype
在使用Ext JS编写应用时,很多时候通过定义xtype来指定该位置使用什么组件,例如2.3节的示例中的“xtype:"panel"”,这里指定使用面板作为当前位置的组件。这样做的主要目的是简化代码。如果没有xtype,就得先使用变量指向一个组件,然后将其加入父组件中,或者直接在父组件的定义中加入一堆由new关键或Ext.Create方法创建的组件。这不但影响了书写代码的效率,还影响了代码的可读性。有xtype存在,就不用担心这些问题了。
在某些组件下,会默认其内部组件为某些组件,因而也就不需要书写xtype语句。例如,在2.3节的示例中把xtype去掉,代码也能正常运行,因为面板是Viewport内默认的组件。一般来说,没特别声明,使用的都是Panel组件。
定义xtype,一般使用组件的别名。可在API文档的组件说明文档的顶部或Component对象的说明中找到组件的xtype值。
3. 使用new关键字创建对象
在Ext JS 4版本之前,一直使用new关键字创建对象,其语法如下:
new classname([config])
其中calssname是指类名;config是可选参数,为类的配置对象(config options),类型为JSON对象。在2.3节的示例中,Ext.Viewport就是使用该方法创建的。
4.使用Ext.create方法创建对象
Ext.create方法是新增的创建对象的方法,其语法如下:

Ext.create(classname,[config])

其中classname可以是类的全名、别名或备用名;config是可选参数,为类的配置对象(config options),类型为对象。将2.3节的示例中的以下代码:

new Ext.Viewport({
修改为:
Ext.create('Ext.Viewport',{

效果是一样的。那为什么要增加这样一个方法呢?我们来研究一下create方法的源代码。
在ClassManger.js文件中,可以找到以下代码:

Ext.apply(Ext, {
    create: alias(Manager, 'instantiate'),
        ...
})
从代码可知create方法其实是Ext.ClassManager类的instantiate方法的别名,其代码如下:
instantiate: function() {
    var name = arguments[0],
        nameType = typeof name,
        args = arraySlice.call(arguments, 1),
        alias = name,
        possibleName, cls;

    if (nameType != 'function') {
        if (nameType != 'string' && args.length === 0) {
            args = [name];
            name = name.xclass;
        }

        //省略调试代码
        cls = this.get(name);
    }
    else {
        cls = name;
    }
    if (!cls) {
        possibleName = this.getNameByAlias(name);

        if (possibleName) {
            name = possibleName;

            cls = this.get(name);
        }
    }

    if (!cls) {
        possibleName = this.getNameByAlternate(name);

        if (possibleName) {
            name = possibleName;

            cls = this.get(name);
        }
    }

    if (!cls) {
        //省略调试代码

        Ext.syncRequire(name);

        cls = this.get(name);
    }
    //省略调试代码
    return this.getInstantiator(args.length)(cls, args);
},

首先将name变量指向从参数中获取的类名,然后判断name是不是函数,如果不是,且其不是字符串,则从xclass属性中获取类名。接着使用get方法获取对象,并将cls变量指向对象。
get方法的源代码如下:

get: function(name) {
    var classes = this.classes;
    if (classes[name]) {
        return classes[name];
    }
    var root = global,
        parts = this.parseNamespace(name),
        part, i, ln;
    for (i = 0, ln = parts.length; i < ln; i++) {
        part = parts[i];
        if (typeof part != "string") {
            root = part;
        } else {
            if (!root || !root[part]) {
                return null;
            }
            root = root[part];
        }
    }
    return root;
},

代码中的classes对象包括了Ext JS的所有类,因而代码首先根据name从classes中寻找类,如果存在,则返回对象;如果不存在,则说明是用户自定义的类,需要从Ext.global中寻找。
查找工作首先要做的是使用parseNamespace方法拆解类名,其代码如下:

parseNamespace: function(namespace) {
        //省略调试代码
    var cache = this.namespaceParseCache;

    if (this.enableNamespaceParseCache) {
        if (cache.hasOwnProperty(namespace)) {
            return cache[namespace];
        }
    }

var parts = [],
    rewrites = this.namespaceRewrites,
    root = global,
    rewrite, from, to, i, ln;

    for (i = 0, ln = rewrites.length; i < ln; i++) {
        rewrite = rewrites[i];
        from = rewrite.from;
        to = rewrite.to;

        if (namespace === from || namespace.substring(0, from.length) === from) {
            namespace = namespace.substring(from.length);

            if (typeof to !== "string") {
                root = to;
            } else {
                parts = parts.concat(to.split("."));
            }

            break;
        }
    }

    parts.push(root);

    parts = parts.concat(namespace.split("."));

    if (this.enableNamespaceParseCache) {
        cache[namespace] = parts;
    }

    return parts;
},

代码中namespaceParseCache对象的作用是使用类名作为关键字并指向拆解后的类名数组,这样,当该类被多次使用时,就可以直接从namespaceParseCache对象中获取拆解的类名数组,而不需要再拆解一次,从而加快运行速度。
通过enableNamespaceParseCache属性可配置是否开启namespaceParseCache对象的缓存功能,默认是开启的。如果在enableNamespaceParseCache中已存在类名的拆解结果,则返回结果。
属性namespaceRewrites的定义如下:

namespaceRewrites: [{
    from: 'Ext.',
    to: Ext
}],

在其他文件中找不到为namespaceRewrites添加数据的代码,因而在循环中,如果类名是以“Ext.”开头的,root会指向Ext对象;如果不是,root就是初始值,指向Ext.global。
接着,将root指向的对象存入parts数组,再将拆分类名产生的数组与parts数组合并。如果开启了缓存功能,在namespaceParseCache对象中,将以类名为关键字指向parts数组,最后返回parts数组。数组返回后,通过循环的方式来查找类定义。因为返回数组(parts)的第1个数据不是Ext对象就是Ext.golbal对象,因而变量root在第一次循环时,会指向Ext对象或Ext.golbal对象。在后续循环中,会根据拆分的类名在Ext或Ext.gdbal对象中逐层找下去。如果期间“root[part]”不是对象,说明不存在该类,返回null。如果找到了,返回root指向的对象。
如果cls不是指向对象,则尝试使用别名方法查找对象。查找时,首先使用getName-ByAlias方法将别名转换为类名,其代码如下:

getNameByAlias: function(alias) {
        return this.maps.aliasToName[alias] || '';
},
在maps属性中保存了以下3个对象:
maps: {
    alternateToName: {},
    aliasToName: {},
    nameToAliases: {}
},

简单来说,maps中的对象就是一个对照表,通过它就可轻松地找到类名和别名。对象alternateToName的作用是通过备用名获得类名,它以备用名作为关键字、类名作为值;对象aliasToName的作用是通过别名获取类名,它以别名作为关键字、类名作为值;对象nameToAliases的作用是通过类名获取别名,它以类名作为关键字、别名作为值。在创建类的时候,会把类名、别名和备用名写入对照表。
如果getNameByAlias方法返回的不是空字符串,说明变量name保存的是别名,需将name修改为类名,然后通过get方法获取对象。如果使用别名也找不到对象,则可尝试使用备用名来查找对象,执行代码与使用别名查找的方式类似。如果还没有找到,则可尝试使用syncRequire方法下载对象,其代码如下:

syncRequire: function() {
    this.syncModeEnabled = true;
    this.require.apply(this, arguments);
    this.refreshQueue();
    this.syncModeEnabled = false;
},

在上面的代码中,syncModeEnabled方法可控制Loader对象的require方法通过同步的方式去下载对象。
如果实在是找不到,就会抛出异常。最后使用getInstantiator方法实例化对象,其代码如下:

getInstantiator: function(length) {
    if (!this.instantiators[length]) {
        var i = length,

            args = [];

        for (i = 0; i < length; i++) {
            args.push('a['+i+']');
        }

        this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
    }

    return this.instantiators[length];
},

代码中的数组instantiators起缓存作用,因为同样的参数长度产生的匿名函数是一样,没必要每次都重新创建一次。最后返回的匿名函数如下:
(function anonymous(c, a) {return new c(a[0], a[1], … ,a[n]);})
代码中的n就是参数的长度,例如length的值为5,则匿名函数如下:
(function anonymous(c, a) {return new c(a[0], a[1], a[2], a[3], a[4]);})
匿名函数返回后会立即执行,参数c指向对象的cls,a指向实例化对象时的参数。也就是说,对象是在匿名函数中实例化的,这样可以保证对象的作用域是安全的。
从以上的分析可以了解到,创建对象的新方法不但可以实现动态加载,而且可以保证作用域的安全,应该优先使用。
5.使用Ext.widget或Ext.createWidget创建对象
Ext.widget的作用是使用别名来创建对象,其语法与2.7.2节介绍的Ext.create是一样的,只是classname使用的是对象的别名。Ext.createWidget是Ext.widget的另外一种使用方法而已,在源代码中的定义如下:

Ext.createWidget = Ext.widget;
Ext.widget的代码如下:
widget: function(name) {
    var args = slice.call(arguments);
    args[0] = 'widget.' + name;

    return Manager.instantiateByAlias.apply(Manager, args);
},
也就是说,它使用ClassManager对象的instantiateByAlias方法创建对象,其代码如下:
instantiateByAlias: function() {
    var alias = arguments[0],
        args = slice.call(arguments),
        className = this.getNameByAlias(alias);

    if (!className) {

        className = this.maps.aliasToName[alias];

        //省略调试代码

        Ext.syncRequire(className);
    }

    args[0] = className;

    return this.instantiate.apply(this, args);
},

代码先是根据别名寻找类名,如果找不到就抛出异常或尝试使用syncRequire方法加载类文件,最后调用instantiate方法创建对象。
6.使用Ext.ns 或 Ext.namespace定义命名空间
在使用C#或Java做开发时,很多时候都会使用命名空间来组织相关类和其他类型。在JavaScript中并没有提供这样的方式,不过可以通过定义一个全局对象的方式来实现,譬如你要定义一个“MyApp”的命名空间,你可以这样:

MyApp ={};

这里要注意,不要使用var语句去定义全局对象。
在Ext JS中,使用Ext.namespace方法可创建命名空间,其语法如下:
Ext.namespace(namespace1,namespace2,…,namespacen)
其中namespace1、namespace2和namespacen都是字符串数据,是命名空间的名字,例如:

//推荐用法
Ext.namespace("MyApp","MyApp.data","MyApp.user");
Ext.ns("MyApp","MyApp.data","MyApp.user");
//或者,不建议使用
Ext.namespace(,"MyApp.data","MyApp.user");
Ext.ns("MyApp.data","MyApp.user");

Ext.ns只是Ext.namespace的简单写法。
在ClassManager.js中可找到Ext.namespace的createNamespace方法的实现代码:

createNamespaces: function() {
  var root = global,
      parts, part, i, j, ln, subLn;

  for (i = 0, ln = arguments.length; i < ln; i++) {
      parts = this.parseNamespace(arguments[i]);

      for (j = 0, subLn = parts.length; j < subLn; j++) {
          part = parts[j];

          if (typeof part !== 'string') {
              root = part;

          } else {
              if (!root[part]) {
                  root[part] = {};
              }

              root = root[part];
          }
      }
  }

  return root;
},

从上面代码可以看到,Ext.namespace创建的命名空间是保存在global对象里的。注意循环结构,数组长度都是先保存到一个局部变量再使用的,原因是JavaScript与C#、Java等语言不同,每次循环都要计算一次数组长度,这样会降低性能。在第一个循环下,使用了parseNamespace方法拆分命名空间的字符串。
在Ext JS初始化时,this指向的是window对象,因而global指向的是window对象。
数组返回到createNamespace方法后,开始执行完循环,最后在window对象下生成了以下结构的全局对象:

{
  MyApp:{
      Data:{}
  }
}

虽然生成的是全局对象,但是在作用域链上,它可以直接在Ext JS的作用域链内搜索对象,而不需要到最外层的全局作用域链搜索对象,这是最大的不同。
在任何编程语言里都不提倡使用全局变量,尤其是在JavaScript里,全局对象在每一层的作用域链里都搜索不到时,才会在全局作用域链里搜索,效率相当低。因此,在JavaScript里不仅不推荐使用全局变量,而且建议当有一个变量不是在当前作用域定义的,并要多次使用时,建议将该变量保存在局部变量中,使用局部变量来进行操作,以避免在域链中多次搜索对象而降低性能。
因此,建议的方法是在Ext对象下创建命名空间,譬如创建以下的命名空间:

Ext.ns("Ext.MyApp","Ext.MyApp.data","Ext.MyApp.user");

最好的方法是使用Ext已定义的命名空间“Ext.app”,如果是扩展或插件则使用“Ext.ux”。
7.使用Ext.define定义新类
在Ext JS 3中,定义新类使用的是Ext.extend方法,因为Ext JS 4的类系统进行了重新架构,所以定义新类的方法也修改为了Ext.define方法,其语法如下:

Ext.define(classname,properties,callback);

其中:
classname:要定义的新类的类名。
properties:新类的配置对象,对象里包含了类的属性集对象,表2-1列出了常用的属性及其说明。
callback:回调函数,当类创建完后执行该函数。

代码中,initConfig方法执行后就会为congfig的属性创建set和get方法,这样创建类的示例后,就可以直接通过set和get方法读写属性的值,譬如例子中用setWidth设置了配置中width的值,使用getHeight获取height的值
 定义静态方法,例如:

Ext.define("subclass",{
      statics:{
          method:function(args){
              return new this(args);
        }
statics   },
           constructor:function(config){
          this.initConfig(config);
          …
      },
      …
    });
    var myclass=subclass.method("class");

类的创建过程将在第4章讲解,下面我们来实践一下。在Firefox中打开2.3节的示例,然后打开Firebug,在控制台中输入以下代码:

Ext.define("Calculator",{
    constructor:function(){
        return this;
    },
    plus:function(v1,v2){
        return v1+v2;
    },
    minus:function(v1,v2){
        return v1-v2;
    },
    multiply:function(v1,v2){
        return v1*v2;
    },
    divid:function(v1,v2){
        return v1/v2
    }
});
var cal=new Calculator();
console.log(cal.plus(87,28)); //115
console.log(cal.minus(87,28)); //59
console.log(cal.multiply(7,8)); //56
console.log(cal.divid(28,7)); //4

代码中定义了一个名称为“Calculator”的类,它包含加、减、乘、除4个方法。运行后,将Firebug标签页切换到DOM标签,可看到如图2-2所示的Calculator类。

继续创建一个继承自Calculator类的新类NewCalculator,新类添加了十进制转换为十六进制的方法,代码如下:

Ext.define('NewCalculator',{
    extend:'Calculator',
    hex:function(v1){
        return v1.toString(16);
    }
});
var ncal=new NewCalculator();
console.log(ncal.hex(28)); //1c

代码中extend属性的值为Calculator,表示NewCalculator将继承自Calculator类。方法hex是新增的进制转换方法。
运行后可在DOM树中看到如图2-3所示的NewCalculator类。

比较一下图2-3与图2-2,可看到Calculator类的超类(superclass)是Ext.Base,而NewCalculator类的超类是Calculator,这说明,没有使用extend属性定义的类会默认从Ext.Base中继承。

继续我们的实践,这次要做的是将HEX、BIN、OCT这3个实现不同进制转换的类混合到NewCalculator类中。第一步要做的是定义3个实现进制转换的类:

Ext.define('HEX',{
    hex:function(v1){
        return v1.toString(16);
    }
});
Ext.define('BIN',{
    bin:function(v1){
        return v1.toString(2);
    }
});
Ext.define('OCT',{
    oct:function(v1){
        return v1.toString(8);
    }
});
然后将HEX、BIN和OCT三个功能混合到继承自Calculator类的NewCalculator类中,这样NewCalculator除了实现加减乘除功能外,还能实现十进制到二进制、八进制和十六进制的转换,代码如下:
Ext.define('NewCalculator',{
    extend:'Calculator',
    mixins:{
        Hex:'HEX',
        Bin:'BIN',
        Oct:'OCT'
    },
    convert:function(value,type){
        switch(type){
            case 2:
                return this.bin(value)
                break;
            case 8:
                return this.oct(value)
                break;
            default:
                return this.mixins.Hex.hex.call(this,value);
                break;
        }
    }
});

var ncal=new NewCalculator();
console.log(ncal.convert(25,2)); //11001
console.log(ncal.convert(25,8)); //31
console.log(ncal.convert(25,16)); //19

在代码中,使用convert方法可进行进制转换,第2个参数type表示要转换的进制类型。
调用mixins属性定义的混合功能有两种方法:第一种是二进制和八进制中使用的直接调用的方法,第二种是十六进制中使用call方法调用的方法。
运行后,在DOM中可看到如图2-4所示的NewCalculator类。

在图2-4中的原型(prototype)节点里,可看到mixins对象中的3个属性都指向了对应的BIN、HEX和OCT对象,而这三个对象中的方法也直接附加到原型上了,这也就解释了为什么可以使用两种方法调用混合功能的方法。要注意的是,如果存在同名方法,譬如将BIN、HEX和OCT定义的方法都修改为convert,那么使用直接调用的方法就会出现错误,因为在JavaScript中,存在同名函数,前面的定义会被最后定义的函数覆盖,所以在不确定是否有同名方法的情况下,建议还是使用第二种call的方法。
定义3个进制转换类实在麻烦,在一个Convert类中,预设好一个type参数,然后根据type定义的类型进行转换就方便多了,代码如下:

Ext.define("Convert",{
    config:{
    type:"hex"
    },
    type_num:16,
    constructor:function(config){
        this.initConfig(config);
        return this;
    },
    applyType:function(type){
        this.type_num= type=="hex" ? 16 : ( type=="oct" ? 8 : 2);
        return type;
    },
    convert:function(v){
        return v.toString(this.type_num);
    }
});
var cv=new Convert();
console.log(cv.convert(29)); //1d
cv.setType("oct");
console.log(cv.convert(29)); //35
cv.setType("bin");
console.log(cv.convert(29)); //11101

在Convert类中,type属性在initConfig执行后会自动生成applyType、setType、getType和resetType这4个方法。当type的值发生改变时,会触发applyType方法,因而可以重写applyType方法以实现所需的功能。在applyType方法中,根据type的值修改了type_num的值,这样在convert方法中就可以使用type_num值直接进行进制转换了。
代码运行后在DOM中可看到如图2-5所示的Convert类。

在图2-5的原型中,可看到与Type有关的4个方法。实现这么简单的功能,每次都要使用new关键字对象太麻烦了。如果是静态类就好了,所以修改代码如下:

Ext.define("Convert",{
    statics:{
        hex:function(v){
            return v.toString(16);
        },
        oct:function(v){
            return v.toString(8);
        },
        bin:function(v){
            return v.toString(2);
        }
    },
    constructor:function(config){
        return this;
    }
});
console.log(Convert.hex(29)); //1d
console.log(Convert.oct(29)); //35
console.log(Convert.bin(29)); //11101

在Convert类中,3个进制转换方法都定义在statics属性中。运行后在DOM树中可看到如图2-6所示的Convert类。

在图2-6中,3个进制转换方法不在原型里,而是直接挂在类节点下。现在大家应该清楚静态类和其他类的区别了。

时间: 2024-09-11 15:36:42

《Ext JS权威指南》——2.7节Ext JS 4语法的相关文章

《Ext JS权威指南》——1.1节学习Ext JS必需的基础知识

1.1 学习Ext JS必需的基础知识 1. JavaScript 嗯,这个还用说吗?Ext JS本来就是一个JavaScript的框架,而且使用Ext JS就需要使用JavaScript语法来开发,需要JavaScript的知识是必然的了.问题的关键是,开发人员对JavaScript知识的掌握也有深浅之分.譬如,我碰到一些开发人员,对JavaScript算是很熟悉了,但是不会JSON,不会直接使用JSON对象,在使用Ext JS的过程中,需要使用JSON对象的时候,居然是通过组装字符串的方式,

《Ext JS权威指南》——1.5节如何获得帮助

1.5 如何获得帮助学习和使用Ext JS或多或少都会遇到一时难以解决的问题,这时候就需要寻求帮助.寻求帮助的方法如下.在线API文档:笔者认为,要提高自己的编程水平,很重要的一点就是经常看和查API文档.很多初学者习惯碰到问题就去论坛或者QQ群问人,这实在不是一个好的办法,因为缺乏思考过程.笔者认为,看API绝对可以提高你解决问题和寻找解决问题的能力,因为看和找的过程就是一个学习的过程.而去问人的过程,基本是一个复制过程,至于为什么要这样?为什么会这样?完全会被忽略.新的API还包含了不少使用

《Ext JS权威指南》——2.2节配置使用Ext JS库

2.2 配置使用Ext JS库要使用Ext JS,首先要做的是将Ext JS包里的resources目录.bootstrap.js文件.ext-all.js文件和ext-all-debug.js文件复制到项目目录.接着在页面中head标记部分添加CSS和脚本文件的引用: <link rel="stylesheet" type="text/css" href="path/resources/css/ext-all.css"/> <

《Ext JS权威指南》——1.4节Ext JS的开发工具的获取、安装与配置介绍

1.4 Ext JS的开发工具的获取.安装与配置介绍 1.4.1 Ext DesignerExt Designer是一个所见即所得的创建Ext JS界面的工具软件,目前版本是1.2版,支持Ext JS 3.x和4.x版本,可在http://www.sencha.com/products/designer/download/下载试用版本. 安装双击下载文件将看到如图1-6所示的语言选择窗口. 选择简体中文后,单击"OK"按钮后将看到如图1-7所示的设定窗口. 单击"前进&quo

《Ext JS权威指南》——2.1节获取Ext JS 4

第2章 从"Hello World"开始 "Hello World"几乎已经成为所有开发类图书的必用案例,本书也不能免俗.本章将通过编写"Hello World"程序来让大家对如何使用Ext JS进行开发有初步的了解,如Ext JS代码是如何运行的.代码书写风格是怎样的.如何实现本地化等.2.1 获取Ext JS 4 要下载Ext JS 4,可访问地址:http://www.sencha.com/products/Ext JS/download/

《Ext JS权威指南》——第1章,第1.0节Ext JS 4开发入门

第1章 Ext JS 4开发入门在这一章,我们将介绍一些与Ext JS有关的基础知识以及Ext JS 4的一些主要变化.从2008年接触Ext JS到现在,不少初学者咨询过我,应该怎样才能学好Ext JS?这是一个很好的问题,每个人的学习方法不同,在学习Ext JS之前的基础都不同,因而如何学好Ext JS因人而异.不过Ext JS始终是一个JavaScript的框架,有其局限性,掌握了Javascript.HTML和CSS等知识,再加上掌握Ext JS的框架结构,就足够应付Ext JS的学习了

《Ext JS权威指南》——导读

目 录 前 言第1章 Ext JS 4开发入门1.1 学习Ext JS必需的基础知识 1.2 JSON概述 1.3 Ext JS 4概述1.4 Ext JS的开发工具的获取.安装与配置介绍 1.5 如何获得帮助 1.6 本章小结 第2章 从"Hello World"开始 2.1 获取Ext JS 42.2 配置使用Ext JS库 2.3 编写"Hello World"程序 2.4 关于Ext.onReady2.5 关于Ext.BLANK_IMAGE_URL2.6 关

《Ext JS权威指南》——2.5节关于Ext.BLANK_IMAGE_URL

2.5 关于Ext.BLANK_IMAGE_URL 在Ext-more.js文件中可找到BLANK_IMAGE_URL属性的默认值和定义.其默认值是: BLANK_IMAGE_URL : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' 定义是: BLANK_IMAGE_URL : (isIE6 || isIE7) ? 'http:/' + '/www.sencha.com/s

《Ext JS权威指南》——1.2节JSON概述

1.2 JSON概述 1.2.1 认识JSON XML虽好,可作为数据交换格式,有时会喧宾夺主,标记比数据还多,徒增流量.更重要的是,在JavaScript中处理XML实在太不便利了.而JSON,没有附加的标记,在JavaScript中可作为对象处理,因而渐渐成了目前Web开发的标准数据交互格式.JSON的英文全称是"JavaScript Object Notation",意思就是JavaScript对象表示法.它是一种基于文本的.独立于语言的轻量级数据交换格式.它来源于ECMA-26