ext/src/class/ClassManager.js
// todo 源码分析
重要:包含了Ext.define的定义
Ext.apply(Ext, { * the class' constructor. * @return {Object} instance * @member Ext * @method create */ create: alias(Manager, 'instantiate'), * * @member Ext * @param {String} [name] The xtype of the widget to create. * @param {Object} [config] The configuration object for the widget constructor. * @return {Object} The widget instance */ widget: function(name, config) { // forms: // 1: (xtype) // 2: (xtype, config) // 3: (config) // 4: (xtype, component) // 5: (component) // var xtype = name, alias, className, T, load; if (typeof xtype != 'string') { // if (form 3 or 5) // first arg is config or component config = name; // arguments[0] xtype = config.xtype; } else { config = config || {}; } if (config.isComponent) { return config; } alias = 'widget.' + xtype; className = Manager.getNameByAlias(alias); // this is needed to support demand loading of the class if (!className) { load = true; } T = Manager.get(className); if (load || !T) { return Manager.instantiateByAlias(alias, config); } return new T(config); }, /** * @inheritdoc Ext.ClassManager#instantiateByAlias * @member Ext * @method createByAlias */ createByAlias: alias(Manager, 'instantiateByAlias'), * required. Otherwise, the override, like the target class, is not included. * * @param {String} className The class name to create in string dot-namespaced format, for example: * 'My.very.awesome.Class', 'FeedViewer.plugin.CoolPager' * It is highly recommended to follow this simple convention: * - The root and the class name are 'CamelCased' * - Everything else is lower-cased * Pass `null` to create an anonymous class. * @param {Object} data The key - value pairs of properties to apply to this class. Property names can be of any valid * strings, except those in the reserved listed below: * - `mixins` * - `statics` * - `config` * - `alias` * - `self` * - `singleton` * - `alternateClassName` * - `override` * * @param {Function} createdFn Optional callback to execute after the class is created, the execution scope of which * (`this`) will be the newly created class itself. * @return {Ext.Base} * @member Ext */ define: function (className, data, createdFn) { //<debug> Ext.classSystemMonitor && Ext.classSystemMonitor(className, 'ClassManager#define', arguments); //</debug> if (data.override) { return Manager.createOverride.apply(Manager, arguments); } // create方法源码见后面 return Manager.create.apply(Manager, arguments); }, /** * Undefines a class defined using the #define method. Typically used * for unit testing where setting up and tearing down a class multiple * times is required. For example: * * // define a class * Ext.define('Foo', { * ... * }); * * // run test * * // undefine the class * Ext.undefine('Foo'); * @param {String} className The class name to undefine in string dot-namespaced format. * @private */ undefine: function(className) { //<debug> Ext.classSystemMonitor && Ext.classSystemMonitor(className, 'Ext.ClassManager#undefine', arguments); //</debug> var classes = Manager.classes, maps = Manager.maps, aliasToName = maps.aliasToName, nameToAliases = maps.nameToAliases, alternateToName = maps.alternateToName, nameToAlternates = maps.nameToAlternates, aliases = nameToAliases[className], alternates = nameToAlternates[className], parts, partCount, namespace, i; delete Manager.namespaceParseCache[className]; delete nameToAliases[className]; delete nameToAlternates[className]; delete classes[className]; if (aliases) { for (i = aliases.length; i--;) { delete aliasToName[aliases[i]]; } } if (alternates) { for (i = alternates.length; i--; ) { delete alternateToName[alternates[i]]; } } parts = Manager.parseNamespace(className); partCount = parts.length - 1; namespace = parts[0]; for (i = 1; i < partCount; i++) { namespace = namespace[parts[i]]; if (!namespace) { return; } } // Old IE blows up on attempt to delete window property try { delete namespace[parts[partCount]]; } catch (e) { namespace[parts[partCount]] = undefined; } }, /** * @inheritdoc Ext.ClassManager#getName * @member Ext * @method getClassName */ getClassName: alias(Manager, 'getName'), /** * Returns the displayName property or className or object. When all else fails, returns "Anonymous". * @param {Object} object * @return {String} */ getDisplayName: function(object) { if (object) { if (object.displayName) { return object.displayName; } if (object.$name && object.$class) { return Ext.getClassName(object.$class) + '#' + object.$name; } if (object.$className) { return object.$className; } } return 'Anonymous'; }, /** * @inheritdoc Ext.ClassManager#getClass * @member Ext * @method getClass */ getClass: alias(Manager, 'getClass'), /** * Creates namespaces to be used for scoping variables and classes so that they are not global. * Specifying the last node of a namespace implicitly creates all other nodes. Usage: * * Ext.namespace('Company', 'Company.data'); * * // equivalent and preferable to the above syntax * Ext.ns('Company.data'); * * Company.Widget = function() { ... }; * * Company.data.CustomStore = function(config) { ... }; * * @param {String...} namespaces * @return {Object} The namespace object. * (If multiple arguments are passed, this will be the last namespace created) * @member Ext * @method namespace */ namespace: alias(Manager, 'createNamespaces') });
create方法源码,如下:
create: function(className, data, createdFn) { //<debug error> if (className != null && typeof className != 'string') { throw new Error("[Ext.define] Invalid class name '" + className + "' specified, must be a non-empty string"); } //</debug> var ctor = makeCtor(); // why? if (typeof data == 'function') { data = data(ctor); } //<debug> if (className) { ctor.displayName = className; } //</debug> data.$className = className; // 详见ExtClass源码 return new Class(ctor, data, function() { var postprocessorStack = data.postprocessors || Manager.defaultPostprocessors, registeredPostprocessors = Manager.postprocessors, postprocessors = [], postprocessor, i, ln, j, subLn, postprocessorProperties, postprocessorProperty; delete data.postprocessors; for (i = 0,ln = postprocessorStack.length; i < ln; i++) { postprocessor = postprocessorStack[i]; if (typeof postprocessor == 'string') { postprocessor = registeredPostprocessors[postprocessor]; postprocessorProperties = postprocessor.properties; if (postprocessorProperties === true) { postprocessors.push(postprocessor.fn); } else if (postprocessorProperties) { for (j = 0,subLn = postprocessorProperties.length; j < subLn; j++) { postprocessorProperty = postprocessorProperties[j]; if (data.hasOwnProperty(postprocessorProperty)) { postprocessors.push(postprocessor.fn); break; } } } } else { postprocessors.push(postprocessor); } } data.postprocessors = postprocessors; data.createdFn = createdFn; Manager.processCreate(className, this, data); }); }
转载于:https://blog.51cto.com/wangyuelucky/1594628