Si vous avez déjà utilisé une version précédente de Ext JS, vous êtes certainement familier avec Ext.extend pour créer une classe:
var MyWindow = Ext.extend(Object, { ... });
Cette approche est facile à utiliser pour créer une nouvelle classe qui hérite d'une autre.
Jeton un coup d'oeil à un autre exemple :
My.cool.Window = Ext.extend(Ext.Window, { ... });
Dans cet exemple nous attribuons un espace de nom à notre nouvelle classe, qui étend Ext.Window. Il ya deux choses que nous avons besoin de noter :
Le premier point est généralement résolu avec Ext.namespace (alias de Ext.ns).
Ext.ns('My.cool');
My.cool.Window = Ext.extend(Ext.Window, { ... });
Le deuxième point, cependant, n'est pas facile à aborder parce Ext.Window pourrait dépendre de plusieurs autres classes qui en hérite directement / indirectement , et à leur tour, ces dépendances peuvent dépendre d'autres classes. Pour cette raison, les applications écrites avant Ext JS 4 comprennent généralement toute la bibliothèque sous forme de Ext-all.js même si on a besoin que d'une toute petite partie du framework.
Ext JS 4 élimine tous ces inconvénients avec une seule méthode que vous devez retenir pour la création de la classe: Ext.define.
La syntaxe de base:
Ext.define({String} className, {Object} members, {Function} onClassCreated);
className
: Le nom de la classemembers
est un objet contenant des paramettres "propriété : valeur"onClassCreated
est une fonction de callBack invoquée que lorsque toutes les dépendances de cette classe sont prêtes, et la classe elle-même est entièrement créé. En raison de la nature asynchrone de la création de nouvelles classes, ce rappel peut être utile dans de nombreuses situations. Ces questions seront abordées à la section IVExemple:
Ext.define('My.sample.Person', {
name: 'Unknown',
constructor: function(name) {
if (name) {
this.name = name;
}
return this;
},
eat: function(foodType) {
alert(this.name + " is eating: " + foodType);
return this;
}
});
var aaron = Ext.create('My.sample.Person');
aaron.eat("Salad"); // alert("Aaron is eating: Salad");
Note que nous avons créé une nouvelle instance de My.sample.Person l'aide de la Ext.create (). Nous aurions pu utiliser le nouveau mot-clé (nouveau My.sample.Person ()). Toutefois, il est recommandé de prendre l'habitude de toujours utiliser Ext.create car il vous permet de prendre avantage du chargement dynamique. Pour plus d'informations sur le chargement dynamique consultez le guide Mise en route
Avant la version 4 de ExtJs, nous n'avions pas vraiment le moyen de distinguer entre les propriétés de la classe et les configurations fournies par l'utilisateur. les propriétés de Configurations sont été définis comme propriétés de la classe normale et documentées à l'aide d'annotation @ cfg. Jetons un coup d'oeil à une classe de l'échantillon. elle est assez longue, mais elle décrit bien les problèmes dans son ensemble:
Ext.ns('My.own');
My.own.Window = Ext.extend(Object, {
/** @readonly */
isWindow: true,
/** @cfg {String} title The default window's title */
title: 'Title Here',
/** @cfg {Object} bottomBar The default config for the bottom bar */
bottomBar: {
enabled: true,
height: 50,
resizable: false
},
constructor: function(config) {
Ext.apply(this, config || {});
this.setTitle(this.title);
this.setBottomBar(this.bottomBar);
return this;
},
setTitle: function(title) {
// Change title only if it's a non-empty string
if (!Ext.isString(title) || title.length === 0) {
alert('Error: Title must be a valid non-empty string');
}
else {
this.title = title;
}
return this;
},
getTitle: function() {
return this.title;
},
setBottomBar: function(bottomBar) {
// Create a new instance of My.own.WindowBottomBar if it doesn't exist
// Change the config of the existing instance otherwise
if (bottomBar && bottomBar.enabled) {
if (!this.bottomBar) {
this.bottomBar = Ext.create('My.own.WindowBottomBar', bottomBar);
}
else {
this.bottomBar.setConfig(bottomBar);
}
}
return this;
},
getBottomBar: function() {
return this.bottomBar;
}
});
En bref, My.own.Window
:
Cette approche a un avantage, mais en même temps est le seul inconvénient : vous pouvez remplacer tous les membres des instances de cette classe lors de l'instanciation, y compris les méthodes et les propriétés privées qui ne devraient jamais être remplacés.
En plus, il existe d'autres limites:
Ext.apply ne fusionne pas les propriétés de l'objet de manière récursive. Donc dans cet exemple, vous ne pouvez pas remplacer bottomBar.height à 60, par exemple, sans fournir d'autres propriétés par défaut de bottomBar.
Getters et setters doivent être définis manuellement pour chaque propriété de configuration. Il n'est pas possible de spécifier clairement quelles sont les propriétés de configuration, par conséquent, setters et getters ne peut pas être généré automatiquement.
En Ext JS 4, nous introduisons une propriété config :
Ext.define('My.own.Window', {
/** @readonly */
isWindow: true,
config: {
title: 'Title Here',
bottomBar: {
enabled: true,
height: 50,
resizable: false
}
},
constructor: function(config) {
this.initConfig(config);
return this;
},
applyTitle: function(title) {
if (!Ext.isString(title) || title.length === 0) {
alert('Error: Title must be a valid non-empty string');
}
else {
return title;
}
},
applyBottomBar: function(bottomBar) {
if (bottomBar && bottomBar.enabled) {
if (!this.bottomBar) {
return Ext.create('My.own.WindowBottomBar', bottomBar);
}
else {
this.bottomBar.setConfig(bottomBar);
}
}
}
});
Et voici un exemple de la façon dont il peut être utilisé :
var myWindow = Ext.create('My.own.Window', {
title: 'Hello World',
bottomBar: {
height: 60
}
});
alert(myWindow.getTitle()); // alerts "Hello World"
myWindow.setTitle('Something New');
alert(myWindow.getTitle()); // alerts "Something New"
myWindow.setTitle(null); // alerts "Error: Title must be a valid non-empty string"
myWindow.setBottomBar({ height: 100 }); // Bottom bar's height is changed to 100
Grâce à ces changements:
Le code de My.own.Window
class' est considérablement réduitLa méthode
apply
est également généré pour chaque propriété de configuration. La méthode de définition auto-généré appelle la méthode apply
en interne avant de définir la valeur. Override the apply
method for a config property if you need to run custom logic before setting the value. If apply
does not return a value then the setter will not set the value. For example see applyTitle
above.Les membres statiques peuvent être définies en utilisant la config statics
.
Ext.define('Computer', {
statics: {
instanceCount: 0,
factory: function(brand) {
// 'this' in static methods refer to the class itself
return new this({brand: brand});
}
},
config: {
brand: null
},
constructor: function(config) {
this.initConfig(config);
// the 'self' property of an instance refers to its class
this.self.instanceCount ++;
return this;
}
});
var dellComputer = Computer.factory('Dell');
var appleComputer = Computer.factory('Mac');
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 prend en charge l'héritage à travers subclassing et mixins. Pour plus d'informations sur l'héritage consultez la documentation de Ext.Class
Une autre nouvelle fonctionnalité introduite dans Ext JS 4 est le chargement dynamique des dépendances. Pour plus d'informations consultez la documentation de Ext.Loader