ViewControllers is used in five Ext JS types.

Source: Internet
Author: User

Original article: Using ViewControllers in Ext JS 5


Introduction

Ext JS 5 provides some exciting improvements in application architecture, such as ViewModels, MVVM, and viewControllers to enhance MVC applications. Most importantly, these options are not mutually exclusive. Therefore, you can introduce these features in incremental mode or mix them together.


Review Controller

In Ext JS 4, the Controller is a class derived from Ext. app. Controller. These controllers use CSS-like selectors (called component queries) to find components and respond to their events. You can also use refs to select or return component instances.

These controllers are created at application startup and exist throughout the application lifecycle. In the lifecycle of the Controller, the view that the controller pays attention to can be said to come and go. A controller may even manage many instances.

Challenges

For large applications, this technology may face some challenges.

In this environment, views and controllers may be developed by multiple development teams and inherited to the final application. It is difficult to ensure that the controller only responds to the view they are interested in. In addition, developers usually want to create a number of controllers within the application startup time limit. Although they can delay the creation of controllers, they cannot be destroyed, so they will remain in the memory when they are no longer needed.


ViewControllers

Although Ext JS 5 is backward compatible with these controllers, it introduces a new type of controller that can be designed to address these challenges: Ext. app. ViewController. ViewController performs the following operations:

  • Simplify the use of listeners and reference configuration items in the view
  • Automatically manage their related ViewController using the life cycle of the View
  • One-to-one associated management view to reduce ViewController complexity
  • Provides encapsulation to make nested views more reliable
  • Retain the ability to select components and listen to their events for any layer on the relevant view
Listeners

Although the listeners configuration item is not new, it is added with new capabilities in Ext JS 5. The new listeners function will be comprehensively discussed in the future article Declarative Listeners in Ext JS 5. For ViewControllers, let's look at two examples. The first is the most basic. Use the listeners configuration item in the child components of the View:

Ext.define('MyApp.view.foo.Foo', {    extend: 'Ext.panel.Panel',    xtype: 'foo',    controller: 'foo',     items: [{        xtype: 'textfield',        fieldLabel: 'Bar',        listeners: {            change: 'onBarChange'  // no scope given here        }    }]}); Ext.define('MyApp.view.foo.FooController', {    extend: 'Ext.app.ViewController',    alias: 'controller.foo',     onBarChange: function (barTextField) {        // called by 'change' event    }}); 

In the listeners Code above, an onBarChange is used, but no scope is specified ). Within the Event System, the scope of the Bar text field is resolved to its ViewController.

In the past, the listeners configuration item was reserved for the component creator. How can a view listen to its own events and trigger its base class? The solution is to use an explicit scope:

Ext.define('MyApp.view.foo.Foo', {    extend: 'Ext.panel.Panel',    xtype: 'foo',    controller: 'foo',     listeners: {        collapse: 'onCollapse',        scope: 'controller'    },     items: [{        ...    }]});

The above sample code utilizes two new functions of Ext JS 5: named scope and declarative listening. The focus here is the scope of the name. Here, two valid scopes can be used: this and controller. When writing an MVC application, the controller is always used, not to mention the ViewController of the view (not the ViewController of the view instance created ).

Because a view is a type of Ext. Component, you can define an xtype for it so that other views can create view instances and their text fields in the same way. To explore how to integrate these ideas, consider how to use the change view, for example:


Ext.define('MyApp.view.bar.Bar', {    extend: 'Ext.panel.Panel',    xtype: 'bar',    controller: 'bar',     items: [{        xtype: 'foo',        listeners: {            collapse: 'onCollapse'        }    }]});

In this case, the Bar view creates an instance of the Foo view as its sub-component. In addition, a collapse event is bound to the Foo view. In earlier versions of Ext JS or Sencha Touch, these declarations will conflict, and in Ext JS 5, they will be resolved as expected. The listener declared through the Foo view is only triggered in the Foo ViewController, while the listener declared in the Bar view is only triggered in the Bar ViewController.


Reference)

When writing the Controller logic, the most annoying thing is to obtain the required components to complete only operations, such:


Ext.define('MyApp.view.foo.Foo', {    extend: 'Ext.panel.Panel',    xtype: 'foo',    controller: 'foo',     tbar: [{        xtype: 'button',        text: 'Add',        handler: 'onAdd'    }],     items: [{        xtype: 'grid',        ...    }]}); Ext.define('MyApp.view.foo.FooController', {    extend: 'Ext.app.ViewController',    alias: 'controller.foo',     onAdd: function () {        // ... get the grid and add a record ...    }});

How can I obtain grid components now? In Ext JS 4, you can use refs configuration items or some other methods to find components. Therefore, these technologies require placing some properties on the grid that can be used to identify and uniquely identify the grid. The old technology uses the id configuration item (Ext. getCmp) or itemId (applicable to refs or some component query syntax. The advantage of using id is that you can achieve quick search, but you must ensure that this identifier is unique in the entire application or DOM, and this method is not desirable. Using itemId or other queries is more flexible, but you need to search for the required components.

You can use the new reference configuration item in Ext JS 5. You only need to add the reference to the grid and use lookupReference to obtain it:

Ext.define('MyApp.view.foo.Foo', {    extend: 'Ext.panel.Panel',    xtype: 'foo',    controller: 'foo',     tbar: [{        xtype: 'button',        text: 'Add',        handler: 'onAdd'    }],     items: [{        xtype: 'grid',        reference: 'fooGrid'        ...    }]}); Ext.define('MyApp.view.foo.FooController', {    extend: 'Ext.app.ViewController',    alias: 'controller.foo',     onAdd: function () {        var grid = this.lookupReference('fooGrid');    }});

This is similar to allocating an itemId named fooGrid and executing "this. down ('# fooGrid ')". However, the underlying implementation is different and the difference is great. First, the reference configuration item registers the component itself to the view to which it belongs (usually identified in ViewController ). Second, the lookupReference method only queries the cache to determine whether to refresh the reference (the add or remove operations of the container ). If everything goes well, a reference can be returned from the cache. In addition, the pseudo code is as follows:


 lookupReference: (reference) {    var cache = this.references;    if (!cache) {        Ext.fixReferences(); // fix all references        cache = this.references; // now the cache is valid    }    return cache[reference];} 

That is to say, this does not need to be searched and will not cause problems due to the addition or deletion of sub-components of containers. As we can see, the advantage is that efficiency is provided.


Encapsulation)


Although the implementation of selector in Ext JS is flexible, there are also some risks. In fact, these selectors can "see" All component hierarchies, which are both powerful and prone to errors. For example, a controller can run normally during the isolation operation, but once other views are introduced, it will fail because its selector may accidentally match the new view.

These problems can be managed through the following methods. However, when listeners or references are used in ViewController, it is impossible to solve these problems. This is because the listeners and references configuration items can only connect to the ViewController to which they belong. In a view, you can use any unique reference value because the view knows that these names are not exposed to the view creator.

Similarly, the listeners can be retained to the ViewController to which the listeners belongs, instead of distributing it to the event processing of other controllers that use the wrong selector unexpectedly. Although the listening takes precedence over the selector, the two mechanisms can work together when the selector is needed.

To achieve this, the view needs to use its ViewController to trigger the event. There is an auxiliary method in ViewController that can be used to implement this: fireViewEvent, for example:


Ext.define('MyApp.view.foo.FooController', {    extend: 'Ext.app.ViewController',    alias: 'controller.foo',     onAdd: function () {        var record = new MyApp.model.Thing();        var grid = this.lookupReference('fooGrid');        grid.store.add(record);         this.fireViewEvent('addrecord', this, record);    }}); 

The creator of the view can use a standard listener:


 Ext.define('MyApp.view.bar.Bar', {    extend: 'Ext.panel.Panel',    xtype: 'bar',    controller: 'bar',     items: [{        xtype: 'foo',        listeners: {            collapse: 'onCollapse',            addrecord: 'onAddRecord'        }    }]});

Listeners and event Domains

In Ext JS 4.2, MVC event distribution is generalized to reference the event domain. Event domains intercept events when they are triggered and distribute them to controllers controlled by selector matching. Although other fields only have a limited selector, the component event field has a complete component query selector.

In Ext JS 5, each ViewController creates an instance named view for a new event domain. This event field allows ViewController to use the standard implicit restriction that its scope is the listen or control method of the view. It also adds a specific choice to match the view itself.

Ext.define('MyApp.view.foo.FooController', {    extend: 'Ext.app.ViewController',    alias: 'controller.foo',     control: {        '#': {  // matches the view itself            collapse: 'onCollapse'        },        button: {            click: 'onAnyButtonClick'        }    }}); 

The code above shows the difference between listeners and selector. The selector button can match any button in the view and sub-view (regardless of depth, even the sun view). That is to say, the selector-based processing does not care about the encapsulation boundary and changes the behavior with the previous Ext. app. the behavior of the Controller is consistent. In a limited case, this is a very practical technology.

Finally, the event domain will follow the nesting and effectively bubble up the event according to the view level. That is to say, when an event is triggered, it will first be passed to any standard listeners. It is then passed to the ViewController to which it belongs, and then passed to the top layer through its parent ViewController (if any. Finally, the event is passed to the standard component event domain for processing by the Controller derived from Ext. app. Controller.

Lifecycle

A common technique for large applications is to dynamically create the desired controller as needed. This helps reduce the loading time of the application, and helps at run time by not activating the potential controller that already provides performance. This is not possible in the previous version. Once a controller is created, it will remain active in the application and will not be destroyed and released. Similarly, this does not change the fact that a controller may contain any number of related views (including those without views.

However, ViewController is created early in the life cycle of a component and binds its entire life cycle to the view. When a view is destroyed, ViewController also destroys the view. This means that ViewController does not need to be forced to manage the status when there are no views or many views.

This one-to-one management means that the reference trace is simplified and will no longer leak easily due to component destruction. ViewController can implement any method to process transactions at any key point in its lifecycle.

Beforeinit -- this method can be rewritten and executed before the view calls the initComponent method. This method will be called immediately after the controller is created, and this will occur within the component's constructor when the initConfig method is called.

Init -- this method will be called shortly after the view calls the initComponent method. This usually occurs when the controller is initialized after the view is initialized,

InitViewModel -- this method is called when the ViewModel of a view is created (if any.

Destroy -- clear any resources (make sure the callParent method is called ).

Summary


We believe that ViewController will greatly simplify your MVC application. They can also be used with ViewModels. Therefore, you can combine these methods and their respective advantages. We are very excited to publish the official version and see the improvements made in your application.


Author: Don griin
Don Griffin is a member of the Ext JS core team. he was an Ext JS user for 2 years before joining Sencha and has over 20 years of software engineering experience on a broad range of platforms. his experience designing web application front-ends and back-ends, native GUI applications, network protocols and device drivers. don's passion is to build world class products that people love to use.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.