澳门游戏平台大全 澳门游戏平台大全 6应用程序Build后出现,4官方文档之三

6应用程序Build后出现,4官方文档之三

概述

在对Ext JS 6的应用程序打包后,时不时会出现以下错误:

澳门游戏平台大全 1

由于是压缩后出现的错误,要进行调试也无从下手,因而这个错误会令新手手足无措,不知道是怎么回事。

Ext JS 4从底层对类体系进行了重构,这是Ext
JS历史上的第一次对类体系的巨大重构。新的架构几乎被应用到每一个Ext JS
4的类中,所以希望您在开始编码前能对它有一定的了解,这是非常重要的。
这篇手册适用于任何想创建新类或者继承Ext JS
4中现存类的开发人员,分为4部分: 第一部分: “概述” —
解释了创建一个强健的类体系的必要性 第二部分: “命名规范” —
讨论了对类、方法、属性、变量和文件的最佳命名规范 第三部分: “实践” —
提供了详细的一步一步的代码示例 第四部分: “错误处理和调试” —
提供了非常有用的关于如何处理异常的秘诀和技巧 澳门游戏平台大全,一. 概述 Ext JS
4拥有超过300个类,迄今为止,我们已经有一个超过200,000开发者的庞大社区,他们来自世界各地的各种编程背景。对于如此大规模的一个框架,我们面临着一个巨大的挑战来提供一个通用的代码体系结构:
友好并易于学习 开发迅速,容易调试,部署简单 组织良好,可扩展和可维护
JavaScript是一个无类型的,面向原型的语言,这种语言最强大的特性之一就是灵活性。它可以通过各种不同的方法,使用各种不同的编码风格和技巧来完成同一个工作。然而,这种特性却带来了一个不可预见的代价,如果没有一个统一的结构,JavaScript代码就很难理解、维护和重用。
基于类的编程,换句话说,使用最流行的OOP模型。基于类的语言通常是强类型语言,提供了封装,并有标准的编码约定。一般情况下,让开发者遵循一组统一的编码规则,写的代码才更可能是可预测的,可扩展的和可延伸的。然而,它们却没有了像JavaScript这类语言一样的动态能力。
每种方法都有它们自己的优缺点,但是我们能否同时利用它们两者的优点部分,而隐藏它们的缺点部分呢?答案是肯定的,我们已经在Ext
JS 4中实现了这个解决方案。 二. 命名规范
在你的代码中始终使用一致的基于类、命名空间和文件名的命名规范,这将有助于保持你的代码易组织、结构化和易读。
1) 类
类名可以只包含字母数字字符,数字在大多数情况下是不允许的,除非它们属于一个技术术语。不要使用下划线,连字符,或任何其他非字母数字字符。例如:
MyCompany.useful_util.Debug_Toolbar 是不可以的 MyCompany.util.Base64
是可以的
类名应该通过使用对象的点表达式属性,从而放置到适当的命名空间中。至少,类名应该有一个唯一的顶层命名空间。例如:
MyCompany.data.CoolProxy MyCompany.Application
顶层命名空间和类名都应该采用驼峰命名法,除此之外,其他的应该全部小写。例如:
MyCompany.form.action.AutoLoad 不是由Sencha的Ext
JS发布的类不能使用Ext作为顶层命名空间。
缩略词也应该遵循上述的驼峰命名规范。例如: Ext.data.JsonProxy 代替了
Ext.data.JSONProxy MyCompany.util.HtmlParser 代替了
MyCompary.parser.HTMLParser MyCompany.server.Http 代替了
MyCompany.server.HTTP 2) 源文件
类的名称直接映射到存储它们的文件路径中,因此,每一个文件只能有一个类,例如:
Ext.util.Observable 存储在 /to/src/Ext/util/Observable.js
Ext.form.action.Submit 存储在 /to/src/Ext/form/action/Submit.js
MyCompany.chart.axis.Numeric 存储在
/to/src/MyCompany/chart/axis/Numeric.js
路径/to/src是您的应用程序的类的根目录,所有类都应该放置在这个共同的根目录下。
3) 方法和变量
与类名类似,方法和变量名可以只包含字母数字字符,数字在大多数情况下是不允许的,除非它们属于一个技术术语。不要使用下划线,连字符,或任何其他非字母数字字符。
方法和变量名也应该总是驼峰式的,这也适用于缩略词。 示例:
可接受的方法名称: encodeUsingMd5代替了getHTML代替了
getJSONResponse代替了parseXMLContent() 可接受的变量名称: var
isGoodName, var base64Encoder, var xmlReader, var httpServer 4)
属性
类属性名完全遵循与上述的方法和变量相同的命名规范,除了静态常量。
静态类属性即常量应该全部大写,例如: Ext.MessageBox.YES = “Yes”
Ext.MessageBox.NO = “No” MyCompany.alien.Math.PI = “4.13” 三. 实践
1. 声明 1.1) 老的方法 如果您曾经使用过任何先前版本的Ext
JS,您肯定很熟悉使用Ext.extend来创建类: var MyWindow = Ext.extend;
这种方法很容易创建一个继承自其他类的新类,然而除了直接继承,我们没有一个很好的API来创建类的其他方面,如配置,静态配置和混入类,我们稍后将详细回顾它们。
让我们看看另外一个例子: My.cool.Window = Ext.extend;
在这个示例中,我们希望创建一个新的具有命名空间的类,并让它继承Ext.Window,这里有两个问题需要解决:
My.cool 必须是已存在的命名空间对象,这样我们才能分配Window作为其属性
Ext.Window 必须存在且被加载,这样才能引用它
第一点通常用Ext.namespace来解决,这个方法递归地创建不存在的对象,而让人厌烦的是你必须总是记得把它们添加到
Ext.extend 之前: Ext.ns;My.cool.Window = Ext.extend;
然而第二个问题就不太容易解决了,因为
Ext.Window可能依赖于很多其他的类,它可能是直接地或间接地继承自那些依赖类,而这些依赖类可能又依赖于其他类。由于这个原因,在Ext
JS 4之前编写的应用程序通常都会引入整个库文件
ext-all.js,尽管可能仅仅只需要其中的很小一部分。 1.2) 新的方法 Ext JS
4消除了所有这些缺点,您只需要记得唯一的一个创建类的方法是:Ext.define,它的基本语法如下:
Ext.define(className, members, onClassCreated); className: 类名 members
是一个大对象,代表了一个类成员的集合,是一系列的键-值对 onClassCreated
是一个可选的回调函数,当类的所有依赖项都准备好了,并且类被完全创建时,就会被调用。这个回调函数在很多情况下是很有用的,我们将在第四部分中深入讨论。
示例: 复制代码 代码如下:
Ext.define(‘My.sample.Person’,{ name: ‘Unknown’, constructor: function {
this.name = name; }}, eat: function { alert(this.name + ” is eating: ” +
foodType); }}); var aaron = Ext.create(‘My.sample.Person’, ‘Aaron’);
aaron.eat; // alert(“Aaron is eating: Salad”); 注意,我们是用
Ext.create()方法创建了一个My.sample.Person的实例。当然我们也可以使用new
关键字(new My.sample.Person,然而我们建议您养成总是使用 Ext.create
的习惯,因为它可以利用动态加载功能。更多关于动态加载的信息,请看Ext JS
4入门指南。 2. 配置 在Ext JS
4中,我们引入了一个专用的config属性,它会在类创建前,由强大的预处理器类
Ext.Class 进行处理,具有如下特性: 配置是从其他类成员完全封装的
每个config属性的getter和setter方法会在类原型中自动的生成,如果类里没有定义这些方法的话
同时,也会为每个config属性生成一个apply方法,自动生成的setter方法会在内部设置值之前调用这个apply方法。如果你想要在设置值之前运行自定义逻辑,就可以覆盖这个apply方法。如果apply没有返回值,setter方法将不会设置值。让我们看看下面的applyTitle方法:
下面的例子定义了一个新类: 复制代码
代码如下: Ext.define(‘My.own.Window’, { /** @readonly */ isWindow:
true, config: { title: ‘Title Here’, bottomBar: { enabled: true, height:
50, resizable: false } }, constructor: function { this.initConfig; },
applyTitle: function { if || title.length === 0) { alert(‘Error: Title
must be a valid non-empty string’); } else { return title; } },
applyBottomBar: function { if (bottomBar && bottomBar.enabled) { if {
return Ext.create(‘My.own.WindowBottomBar’, bottomBar); } else {
this.bottomBar.setConfig; 下面是如何使用这个新类的例子: 复制代码 代码如下: var myWindow =
Ext.create(‘My.own.Window’, { title: ‘Hello World’, bottomBar: { height:
60 }}); alert; // alerts “Hello World” myWindow.setTitle; alert; //
alerts “Something New” myWindow.setTitle; // alerts “Error: Title must
be a valid non-empty string” myWindow.setBottomBar; // Bottom bar’s
height is changed to 100 3. 静态配置
静态配置成员可以使用statics属性来定义: 复制代码 代码如下: Ext.define(‘Computer’, {
statics: { instanceCount: 0, factory: function { // ‘this’ in static
methods refer to the class itself return new this; } }, config: { brand:
null}, constructor: function { this.initConfig; // the ‘self’ property
of an instance refers to its class this.self.instanceCount ++; }}); var
dellComputer = Computer.factory;var appleComputer = Computer.factory;
alert(appleComputer.getBrand; // using the auto-generated getter to get
the value of a config property. Alerts “Mac”
alert(Computer.instanceCount); // Alerts “2” 四. 错误处理和调试 Ext
JS 4包含了一些有用的特性,可以帮助你调试和错误处理:
你可以使用Ext.getDisplayName()方法来获取任何方法的显示名称,这是特别有用的,当抛出错误时,可以用来在错误描述里显示类名和方法名:
throw new Error(‘[‘ + Ext.getDisplayName + ‘] Some message here’);
当错误从由Ext.define()定义的类的任何方法中抛出时,如果你使用的基于WebKit的浏览器的话,你会在调用堆栈中看到方法名和类名。例如,下面是从Chrome中看到的堆栈信息:

错误原因

造成该错误的主要原因是要创建的类在打包时没有包含在包内,又或者是类名错误造成的。我遇到的一个比较典型的错误就是在requires中使用了Ext.MessageBox而不是Ext.window.MessageBox,就会出现该错误。

解决办法

虽然知道该错误是由于类名造成的,但苦于无法知道是那个文件中的requires出现的问题,因而要解决这个问题也很棘手,不过主要有足够耐心,还是能解决的。

该错误出现的地方是在应用程序extpackagescoresrcclass目录下的ClassManager.js文件中的getInstantiator方法内,代码如下:

getInstantiator: function(length) {
    var instantiators = this.instantiators,
        instantiator,
        i,
        args;

    instantiator = instantiators[length];

    if (!instantiator) {
        i = length;
        args = [];

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

        instantiator = instantiators[length] = new Function('c', 'a', 'return new c(' + args.join(',') + ')');
        //
        instantiator.name = "Ext.create" + length;
        //
    }

    return instantiator;
},

错误中的代码就是由“instantiator=”这句代码(文件的895行)自动生成的。这段代码的主要作用是创建一个新的类实例并返回该实例,而当该类不存在或类名错误的时候,因为创建不了类的实例,就会出现错误。

出现问题的地方已经找到,但要解决问题,不能在这里,因为在该函数内要查找是那个类出现错误,也很困难,因为调用该类的时候传递给该类的可能是一个空的类名,因而,需要在调用该方法时去查。

通过在ClassManager.js文件中搜索getInstantiator,会发现在create方法内调用了该方法,代码如下:

create: function () {
    var name = arguments[0],
        nameType = typeof name,
        args = arraySlice.call(arguments, 1),
        cls;

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

        //
        if (typeof name !== 'string' || name.length < 1) {
            throw new Error("[Ext.create] Invalid class name or alias '" + name +
                            "' specified, must be a non-empty string");
        }
        //

        name = Manager.resolveName(name);
        cls = Manager.get(name);
    }

    // Still not existing at this point, try to load it via synchronous mode as the last resort
    if (!cls) {
        //
        //
        !isNonBrowser &&
        //
        Ext.log.warn("[Ext.Loader] Synchronously loading '" + name + "'; consider adding " +
             "Ext.require('" + name + "') above Ext.onReady");
        //

        Ext.syncRequire(name);

        cls = Manager.get(name);
    }

    //
    if (!cls) {
        throw new Error("[Ext.create] Unrecognized class name / alias: " + name);
    }

    if (typeof cls !== 'function') {
        throw new Error("[Ext.create] Singleton '" + name + "' cannot be instantiated.");
    }
    //

    return Manager.getInstantiator(args.length)(cls, args);
},

注意最后一句,可以看到调用getInstantiator方法,传递了两个参数,而第一参数,根据上面的代码可知道这就是类名或类自身,这时候,一般通过在return语句上面添加“console.log(cls)”就可知道是那个类出现问题了。

特殊情况是cls为空的时候,就不知道错误出在哪里了。这时候,就需要在return语句前添加debugger语句,在调用该方法时,在浏览器进入调试状态来查了。其实这是一个很烦人的过程,因为类的创建过程都会调用该方法,因而这个需要耐心,一直等到错误出现的时候。而且这个过程可能要重复一次才行,因为错误是在debugger后产生,你需要记录的是这个错误是在什么时候产生,这个很重要。

当知道错误是在什么时候发生了,就可以在debugger进入调试状态的时候,在浏览器的调试工具中,查看栈信息,以确定那个类调用了该方法造成的错误,从而知道错误是产生在那个类。知道了错误在那个类,就好办了,用排除法就可以很容易知道是那个地方出问题了。

以上步骤修改代码后,都要build一次再调试。

由于该错误一时很难还原,栈调试无法以图片显示,在此深表遗憾,如果有需要,可加群391747779进行咨询。

BTY:貌似在最新版的Sencha CMD中已消除了该错误。

JS 6应用程序Build后出现“c is not a
constructor return new c(a[0])”的处理 概述 在对Ext JS
6的应用程序打包后,时不时会出现以下错误: 由于是…

Ext JS 6应用程序Build后出现“c is not a constructor return new c(a[0])”的处理

标签:, , , ,

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图