自已扩展EXT组件(Extending Ext Components)
自已扩展EXT组件
From Learn About the Ext JavaScript Library
Summary: Gives an overview on how to extend Components in Ext and provides links to the many great articles that have been written on the subject by Ext community members |
Author: Patrick Donelan |
Published: 2008-04-16 |
Ext Version: 2.0 |
Languages: English |
Contents[hide] |
Introduction
In the beginning there was Ext.extend() and it was good. Ext.extend() lets you build powerful object-oriented class hierarchies in javascript. You can use it to build your own base classes and derived classes, and also to extend Ext's built-in classes. If you are not familiar with Ext.extend() you should start by reading Manual:Intro:Inheritance.
Jozef Sakalos' Tutorial:Extending_Ext_Class gives a great step-by-step account of how to use the Ext 1.x approach to inheritance. It is well worth a read as the define-your-own-constructor approach still works in Ext 2.x and you will no doubt encounter pre-2.x code that uses this approach.
Ext.Component
Most Ext widgets (Form elements, Panels, Toolbars, ..) inherit from Ext.Component (and those that don't will in Ext 3).
Pre-configured Classes
The simplest way you can extend Ext.Component (or any class that inherits from it) is to do what you would have already done in Ext 1.x and use Ext.extend() (as per Jozef's tutorial above). The difference though, is that you do not need to define your own constructor (this is handled by the initComponent() function which is covered later in this article). If all you want to do is define a few of your own defaults as a re-usable class (referred to here and elsewhere in the ExtJS community as a Pre-configured Class), all you have to do is:
// Create MyComponent which is a pre-configured version of Ext.some.component MyComponent = Ext.extend(Ext.some.component, { myDefault1: '..', myDefault2: '..' }); // register xtype to allow for lazy initialization Ext.reg('mycomponentxtype', MyComponent);
In the example above the object literal that you pass as the second argument to Ext.extend() would contain your overwritten defaults for the config options that Ext.some.component already supports.
The above example is deceptively simple but allows you to refactor large chunks of repetitive code out of your application into re-usable objects. For example, you can then create instances of Ext.some.component with your pre-configured config options via:
var myComponent = new MyComponent();
Or lazily via the Component XType you registered, e.g. in a list of Panel items via:
{.. items: [ {xtype: 'mycomponentxtype'} ] ..}
Extending Ext.Component
Ok, so Pre-configured Classes are useful, but so far we haven't added any extra capabilities to the classes we are inheriting from. To do that we need to override some inherited methods. This is where Ext 2.x really starts to shine.
Ext.Component existed in 1.x but in 2.x it was further expanded and improved upon, making it one of the most fundamental classes in the overall architecture. Component now provides a unified model for component creation, rendering, event handling, state management and destruction, and every component in Ext that requires these features now extends Component. Ext_2_Overview#Component_Model.
You should study the above linked Ext_2_Overview well as this document isn't much more than an elaboration on what that article lays out. You'll find that if you open up the source code for Ext.Component (it's the file called Component.js in the widgets sub-folder of the ExtJS src folder - refer to my Ext Source Overview article if you're not sure how) the code can be followed line-by-line along with the corresponding step-by-step explanation of the Component Life Cycle, Ext_2_Overview#Rendering and Ext_2_Overview#Destruction. Really eye-opening stuff if you want to start grokking how Ext works under the hood!
Now, since this article is about extending Ext.Component, the primary method you want to focus on extending is initComponent() which takes a starring role in the Component Life Cycle. After you have mastered initComponent() you can move on to other important methods such as onRender() which lets you extend Ext_2_Overview#Rendering, onDestroy() for component Ext_2_Overview#Destruction etc.. Rather than re-hashing what has been written elsewhere, at this point I'll just point you at some of the great resources that have been written by other Ext community members.
Jozef Sakalos' Tutorial:Writing_a_Big_Application_in_Ext gives a great step-by-step tutorial on using the new Component inheritance model and why it's undoubtedly a good thing for any non-trivial application.
Also by Jozef Sakalos, Tutorial:Extending_Ext2_Class also provides a great real-world example to work through (mjlecomte's forum post provides a more heavily-commented version of the same code).
A Re-usable Template
The following is a template (based on the template posted by Jozef Sakalos in mjlecomte's forum post) that you can use as a starting-point when extending Ext.Component classes
MyComponent = Ext.extend(Ext.some.component, { // Constructor Defaults, can be overridden by user's config object propA: 1, initComponent: function(){ // Called during component initialization // Config object has already been applied to 'this' so properties can // be overriden here or new properties (e.g. items, tools, buttons) // can be added, eg: Ext.apply(this, { propA: 3 }); // Before parent code // Call parent (required) MyComponent.superclass.initComponent.apply(this, arguments); // After parent code // e.g. install event handlers on rendered component }, // Override other inherited methods onRender: function(){ // Before parent code // Call parent (required) MyScope.superclass.onRender.apply(this, arguments); // After parent code } }); // register xtype to allow for lazy initialization Ext.reg('mycomponentxtype', MyComponent);
As an enlightening example, if you used the above class via either of the following:
var myComponent = new MyComponent({ propA: 2 }); // Or lazily: {.. items: {xtype: 'mycomponentxtype', propA: 2} ..}
then the property propA would have been set three times, to the values 1, 2, and 3 respectively. If you follow the code (and the comments) through you will see that value starts as 1 (Constructor Default) and then is set to 2 by the user's config object, and finally is overridden in initComponent and set to 3. Hopefully this example gives you a bit of insight into the order in which the code is executed (not in the order that you read it from start to finish!).
Because components nest other components, here's a quick way to grab the top-most component.
var topCmp = (function(o){while(o.ownerCt){o=o.ownerCt} return o;},this);
Closing Remarks
This article focuses primarily on the initComponent() method and its role in the Component Life Cycle. Once you get the hang of that you should start exploring the other aspects of the Ext Component model (managed rendering, state mangement, plugins, etc.) listed in Ext_2_Overview#Component_Model.
Big thanks to Jozef Sakalos who posted all the great tutorials and forum posts on this topic, and of course to Jack and the team for giving us such an awesome framework to build on. Can't wait to see what they come up with in Ext 3!