In the previous article, "in Ext JS 5 using Viewcontrollers", a simple introduction of the Ext JS 5 An important improvement--declarative event monitoring. In this article, we will explore in depth how to use declarative event snooping to simplify the view of your application and reduce boilerplate code for custom components.
Note: The article assumes that you are using ext JS 5.0.1 or later.
What is declarative event snooping?
The so-called "declarative event snooping" refers to the definition of a listener in a class body or the use of a listeners configuration item in an instance's configuration object. Declaring event monitoring in this way is not a new feature of Ext JS 5. In ext JS 4, you can declare event snooping in a class, but only for situations where a function or scope has been defined, such as:
[JavaScript]View Plaincopy
- Ext.define (' MyApp.view.User ', {
- Extend: ' Ext.panel.Panel ',
- Listeners: {
- the//function must be inline or previously defined:
- Collapse: function () {
- //Respond to panel collapse here
- }
- },
- //The method cannot be defined as a handler for collapse:
- Oncollapse: function () {
- }
- });
Because the required processing function cannot use the methods defined in the class, the use of declarative snooping in Ext JS 4 is limited. Developers typically add listening by overriding the InitComponent method and using the on method:
[JavaScript]View Plaincopy
- Ext.define (' MyApp.view.User ', {
- Extend: ' Ext.panel.Panel ',
- InitComponent: function () {
- this.callparent ();
- This.on ({
- Collapse: This.oncollapse,
- Scope: this
- });
- },
- Oncollapse: function () {
- Console.log (this); //The panel instance
- }
- });
Scope resolution
In Ext JS 5, the listeners configuration item was improved, allowing event handling to be specified as a string to correspond to the method name. At run time (any time the event is triggered), the framework resolves these aspects to the actual function reference. We refer to this process as event listener scope resolution.
In ext JS 4, the string handler can be parsed if the scope is explicitly given. In ext JS 5, some special rules have been added to the default scope resolution when declaring a "string" handler without explicitly declaring the scope.
There are two kinds of results for scope resolution: A component or a view controller (Viewcontroller). Regardless of the result, the search starts from the component. The scope is either a component or a view controller, and if not, the framework "crawls" to the upper layer of the component until it finds a suitable component or view controller.
Resolving scopes as components
The first way for the framework to resolve scopes is to look for components that have the Defaultlistenerscope configuration item true. For event listener declarations in a class, the search starts from the component itself.
[JavaScript]View Plaincopy
- Ext.define (' MyApp.view.user.User ', {
- Extend: ' Ext.panel.Panel ',
- Xtype: ' user ',
- Defaultlistenerscope: True,
- Listeners: {
- Save: ' Onusersave '
- },
- Onusersave: function () {
- Console.log (' user saved ');
- }
- });
Listening is defined in the class body of the user view, which means that the framework checks the defaultlistenerscope of the user view itself before lifting the hierarchy. In the current example, the user view sets Defaultlistenerscope to true, and the current listening scope will be resolved to the user view.
For event listeners that are declared in the instance configuration item, the component itself will be over, and the framework will start searching from the parent container, refer to the following code:
[JavaScript]View Plaincopy
- Ext.define (' MyApp.view.main.Main ', {
- Extend: ' Ext.container.Container ',
- Defaultlistenerscope: True,
- Items: [{
- Xtype: ' user ',
- Listeners: {
- Remove: ' Onuserremove '
- }
- }],
- Onuserremove: function () {
- Console.log (' user removed ');
- }
- });
The listener for the user view is declared in the instance's configuration object, which means that the framework skips the user view (although it defines defaultlistenerscope as true) and resolves to the primary view.
Resolving scopes as View controllers
In Ext JS 5, a new controller type--ext.app.viewcontroller is introduced. The view controller is described in detail in "Using Viewcontrollers in ext JS 5", so only the parts related to the view controller and event monitoring are discussed here.
Unlike Ext.app.Controller, which can manage many views, each view controller instance can only bind one view instance. A one-to-one relationship between a view and a view controller allows the view Controller to act as the default scope for event listener declarations in an entry for a view or view.
For Defaultlistenerscope, the same rule applies to view controllers. The class-level listener always searches the component's own view controller before searching the upper layer of the component.
[JavaScript]View Plaincopy
- Ext.define (' MyApp.view.user.User ', {
- Extend: ' Ext.panel.Panel ',
- Controller: ' user ',
- Xtype: ' user ',
- Listeners: {
- Save: ' Onusersave '
- }
- });
- Ext.define (' MyApp.view.user.UserController ', {
- Extend: ' Ext.app.ViewController ',
- Alias: ' Controller.user ',
- Onusersave: function () {
- Console.log (' user saved ');
- }
- });
The above listener is declared within the class body of the user view, and because the user view has its own controller, the framework resolves to usercontroller scope. If the user view does not have its own controller, then the scope resolves to the upper layer.
On the other hand, instance-level snooping skips components and resolves to the parent container on top of the view controller, for example:
[JavaScript]View Plaincopy
- Ext.define (' MyApp.view.main.Main ', {
- Extend: ' Ext.container.Container ',
- Controller: ' main ',
- Items: [{
- Xtype: ' user ',
- Listeners: {
- Remove: ' Onuserremove '
- }
- }]
- });
- Ext.define (' MyApp.view.main.MainController ', {
- Extend: ' Ext.app.ViewController ',
- Alias: ' Controller.main ',
- Onuserremove: function () {
- Console.log (' user removed ');
- }
- });
Merging listeners configuration Items
In ext JS 4, the listener in the base class declaration is completely overridden by the declaration of the listeners configuration item for the class or instance. In Ext JS 5, the listeners API has been improved to properly incorporate event listener declarations in base classes, subclasses, and instances. To understand the behavior, see the following example:
[JavaScript]View Plaincopy
- Ext.define (' BaseClass ', {
- Extend: ' ext.component ',
- Listeners: {
- Foo: function () {
- Console.log (' foo fired ');
- }
- }
- });
- Ext.define (' subclass ', {
- Extend: ' BaseClass ',
- Listeners: {
- Bar: function () {
- Console.log (' bar fired ');
- }
- }
- });
- var instance = New Subclass ({
- Listeners: {
- Baz: function () {
- Console.log (' Baz fired ');
- }
- }
- });
- Instance.fireevent (' foo ');
- Instance.fireevent (' bar ');
- Instance.fireevent (' Baz ');
In Ext JS 4, the above example will only output "Baz", but the Ext JS 5,listeners configuration item will be correctly merged and output "foo bar baz". This allows the class to declare the listener when it is needed without knowing whether the superclass is already listening.
Summary
Our task-declarative monitoring greatly simplifies the definition of event snooping in your application. Combined with a view controller to handle two-way binding of the application's logic and view model, you can also improve the application development experience as much as possible. Try to let us know what you think.
Declarative event monitoring for EXT JS 5