From the translator : Sencha Inc, the manufacturer of the famous Ext JS RIA framework, spoke about the upcoming fourth version on November 22 last year. Release promised was scheduled for February 28.
In order to stir up the interest of the community (after all, the API, according to the developers, has changed significantly), a public alpha or beta version was promised “within a couple of weeks”. Two months have passed, but not yet promised.
Understanding that a marketing mistake was made - they announced a new product too early and thwarted the deadlines for its presentation - the developers decided to cheat a little by laying out the promised beta in parts: package by package.
')
Your attention is invited to the translation of the first article from the official blog of the framework dedicated to the attempt to emulate the "adult" OOP using JavaScript in the implementation of Ext JS 4.
The article, first of all, will be interesting to those who have already used previous versions of the framework - the author hopes that the reader is already familiar with the architecture of Ext JS.
Meet Ext JS 4
Today we are excited to bring to your attention the “firstborn” in a series of completely new features of Ext JS 4. Within a few weeks, we will upload our beta version of Ext JS - package by package. Despite the fact that we initially planned to release a full “beta” somewhere around this time, some parts of the framework stabilize more slowly than we would like, so we decided to publish the packages one by one. Today we will start with an absolutely new class system in Ext JS 4.
JavaScript initially did not include the concept of "class", which could be unusual for beginners. Ext JS has always been packaged with its own class system based on the most powerful prototyping tool. This solution allows programmers to use a more traditional object-oriented approach in development.
With the release of Ext JS 4, we are taking the class system to a new level, adding new features to it that should ease your development and give it even more flexibility. Ext 4 will present four innovations - class declarations, mixins, getters and setters for configurations, as well as dependency loading.

In the illustration above, several advantages of the new class system are noted, for example, Draggable and Resizable have become impurities.
Class declaration
For comparison, let's see how we created a new class in Ext JS 3. In this example, we create a dummy login window that extends the standard Ext.Window class:
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
//Ext JS 3.x class definition MyApp. LoginWindow = Ext. extend ( Ext. Window , { title : 'Log in' , initComponent : function ( ) { Ext. apply ( this , { items : [ { xtype : 'textfield' , name : 'username' , fieldLabel : 'Username' } , ... ] } ) ; MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ; } } ) ;
This approach is very likely familiar to most of you and he copes well with his task, although it is not without flaws. For example, if Ext.Window is not declared before the creation of our class, then the execution of this code will cause an error and our application may crash. Similarly, if the MyApp namespace was not previously declared, we also get an error. Both of these problems are solved if classes are created according to a new ideology:
- // Ext JS 4.x class definition
- Ext. define ( 'MyApp.LoginWindow' , {
- extend : 'Ext.Window' ,
- title : 'Log in' ,
- initComponent : function ( ) {
- Ext. apply ( this , {
- items : [
- // as above
- ]
- } ) ;
- MyApp. LoginWindow . superclass . initComponent . apply ( this , arguments ) ;
- }
- } ) ;
In Ext JS 4, classes can be referenced by a string representation of their names, which means we will never get the errors described above. The class manager is smart enough to check if Ext.Window is already declared. If not, postpone the creation of MyApp.LoginWindow until the required class is available. We are no longer required to follow a clear boot order in our applications, allowing the framework to take care of everything.
Impurities
The first of the new features of the system are
impurities . An admixture is a named declared bundle of behavioral logic and configuration parameters that can be “added” to the class, thereby expanding its capabilities. To take advantage of the impurities, simply apply them to your class declaration.
For example, to make an object of your class move around the screen, it is enough to apply a Draggable admixture to the class. An arbitrary amount of impurities can be “mixed in” with a class — in this way, multiple inheritance can be realized. This is exactly what has been very difficult to achieve over a long time using most JavaScript frameworks.
Impurities are set like this:
- Ext. define ( 'Sample.Musician' , {
- extend : 'Sample.Person' ,
- mixins : {
- guitar : 'Sample.ability.CanPlayGuitar' ,
- compose : 'Sample.ability.CanComposeSongs' ,
- sing : 'Sample.ability.CanSing'
- }
- } ) ;
I will allow myself to repeat, all the class names refer to each other by string names - we will not have errors in the used impurities, if they are not loaded yet. A class can use the capabilities of any amount of impurities, and the impurities themselves are extremely easy to set:
- Ext. define ( 'Sample.ability.CanPlayGuitar' , {
- playGuitar : function ( ) {
- // code to play
- }
- } ) ;
Automatic setters and getters for configurations
Most classes in Ext JS are configured by passing a configuration object to the constructor. Using getters and setters, configuration objects can be changed, and edits applied while the application is running. Ext JS 4 has a configuration option naming convention policy that should be considered when using these features. This approach allows us to reduce development time, API consistency and seriously reduce the size of the downloadable file. Let's look at an example:
- Ext. define ( 'MyClass' , {
- config : {
- title : 'Default Title'
- }
- } ) ;
In the above snippet, we declare a class with a single custom property: title. We also specify the default value for this property, in this case 'Default title'. Thanks to the new class declaration system in Ext JS 4, the framework will automatically create getters and setters for our class. If we used Ext JS 3.3, then we would have to write the template code:
- MyClass = Ext. extend ( MyBaseClass , {
- title : 'Default Title' ,
- getTitle : function ( ) {
- return this . title ;
- } ,
- resetTitle : function ( ) {
- this . setTitle ( 'Default Title' ) ;
- } ,
- setTitle : function ( newTitle ) {
- this . title = this . applyTitle ( newTitle ) || newTitle ;
- } ,
- applyTitle : function ( newTitle ) {
- // custom code here
- }
- } ) ;
Now the library will create for us all four functions. In most cases, a simple update of the values ​​of the variables is sufficient, but there are cases when some action should be taken at the time of the configuration change. For example, if our class displays the header in some DOM element, we have the opportunity to update this element using the following construction:
- xt. define ( 'MyClass' , {
- extend : 'MyBaseClass' ,
- config : {
- title : 'Default Title'
- } ,
- applyTitle : function ( newTitle ) {
- Ext. get ( 'titleEl' ) . update ( newTitle ) ;
- }
- } ) ;
All four functions are created automatically and we can redefine any of them just as easily as we did above with applyTitle. Accordingly, we not only write less code in our classes, but also significantly reduce the size of both ExtJS itself and our application - thus making it easier for the end user to download the file.
Dynamic Download
Only a few advantages of the new class system appeared before us, but much more interesting lies ahead and we will return to it later. However, now is the time to present something absolutely new to your Ext JS 4:
dynamic loading .
Until now, using any version of Ext JS, you had to download the entire library to get started. If you needed to create an object of the Ext.Window class, you had to deflate the class in advance, otherwise an error occurred. Everything has changed and simplified with dynamic loading of Ext JS 4:
- Ext. require ( 'Ext.Window' , function ( ) {
- new Ext. Window ( {
- title : 'Loaded Dynamically!' ,
- width : 200 ,
- height : 100
- } ) . show ( ) ;
- } )
Here we ask Ext JS to load the Ext.Window class and call the ready function. We can request any number of classes by passing an array to Ext.require. Actually, that's all - just to the impossibility, the main magic is hidden from the viewer. The Ext JS 4 dynamic loader works exclusively on the client side and does not require any intervention in the server part. Moreover, it automatically parses the dependencies that the loaded class may have. As an example, let Ext.Window look like this:
- Ext. define ( 'Ext.Window' , {
- extend : 'Ext.Panel' ,
- requires : [ 'Ext.util.MixedCollection' ] ,
- mixins : {
- draggable : 'Ext.util.Draggable'
- }
- } ) ;
Once the library has loaded the Ext.Window class, it defines the dependencies declared in the extend, require sections and in the impurity descriptions.
If any of the required classes have not yet been declared, then the framework will first load the dependency, and then declare Ext.Window. Thanks to the naming convention, the loader automatically knows how to determine the desired file for each of the classes. In this case, the following files will be requested before our function is called:
- src / window.js
- src / Panel.js
- src / util / MixedCollection.js
- src / util / Draggable.js
The loader works recursively - if these files have unrecorded earlier dependencies, it will request files until everything is ready for initialization.
Despite the fact that in the working mode it is recommended not to use the “file by file” mode, this approach allows you to do without one of the oldest and most annoying moments in using Ext JS - the ext-all-debug.js file.
Until recently, we recommended using ext-all-debug.js during development and ext-all.js in the normal mode of the application. The debug version contains the entire library as a whole in a readable form, but also contains about 60,000 lines of code. Accordingly, the difficult process of error correction becomes even more complicated: a hint in the call stack about an exception in the 47657 line of ext-all-debug.js does little to help. On the other hand, the use of a dynamic loader will let you know that the problem of the vonic is in line 56 of the src / data / JsonReader.js file. And all this with a full call stack and the correct line numbers for each file.
In fact, this is a serious step forward in debugging your application, and there will be no problems with performance: in local development it is very difficult to notice that the library is dynamically loaded. The loader also checks for deadlocks and can be used for both synchronous file upload and asynchronous.
If you are not seduced by the above, do not worry. The new class system is
completely compatible with previous versions . Your old classes created with Ext.extend will still work and we will continue to create the ext-all.js file containing the entire library.
Demonstration of opportunities
We created a very simple demo application and
uploaded it to the Internet . The examples begin with the simplest and are gradually complicated in the future. Actually,
an example can be downloaded as an archive and run on a local machine for experiments: all you need is a web server to upload files.
The new class system is the basis for the greatly improved ExtJS 4 library. Each important class in the library has been updated to become faster, so that development would become simpler and more convenient. Over the coming weeks, we will demonstrate the capabilities of our packages in turn, while waiting for Ext JS 4. Next in line is our great data package.