ExtJS 5 brings several exciting architecture improvements: we added support for ViewModels, MVVMs, and ViewControllers to enhance MVC applications. Best of all, these functions are not mutually exclusive, so you can enter them step by step or use them simultaneously.Ext.app.Controller . These controllers use CSS-like selectors (called "Component Queries") to map components and event handlers for their events. They also use the so-called refs for sampling and obtaining instances of components.Ext.app.ViewController . The solution is achieved as follows:listeners and reference , communication with views is simplified.listeners not new, but in Ext JS 5 it acquired new features. A more complete analysis of new listeners will be in the upcoming article - “Declarative Listeners in Ext JS 5”. For use in ViewControllers, we can look at a couple of examples. The first is the usual use of the listeners in the nested view component: Ext.define('MyApp.view.foo.Foo', { extend: 'Ext.panel.Panel', xtype: 'foo', controller: 'foo', items: [{ xtype: 'textfield', fieldLabel: 'Bar', listeners: { change: 'onBarChange' // (scope) } }] }); Ext.define('MyApp.view.foo.FooController', { extend: 'Ext.app.ViewController', alias: 'controller.foo', onBarChange: function (barTextField) { // 'change' } }); onBarChange handler onBarChange not have a specific context ( scope ). The event system for the Bar text field independently makes the default context its own ViewController.listeners config has been reserved for use by the parent component, so the question arises: how can the presentation listen to its own events or perhaps even those that were caused by the base class? The answer is to use an explicit context: Ext.define('MyApp.view.foo.Foo', { extend: 'Ext.panel.Panel', xtype: 'foo', controller: 'foo', listeners: { collapse: 'onCollapse', scope: 'controller' }, items: [{ ... }] }); "this" and "controller" . When we write MVC applications, we almost always use a "controller" , which obviously will be its own ViewController (and not a ViewController of a view that is higher in the hierarchy).Ext.Component , we have assigned the xtype this view, which allows other views to create an instance of it just as we did with the textfield . To see how everything fits together, create a hierarchy: Ext.define('MyApp.view.bar.Bar', { extend: 'Ext.panel.Panel', xtype: 'bar', controller: 'bar', items: [{ xtype: 'foo', listeners: { collapse: 'onCollapse' } }] }); Bar view creates an instance of Foo as one of its elements. Then it listens to the collapse event, just like the Foo view. In previous versions of Ext JS and Sencha Touch, these definitions would conflict. However, in Ext JS 5 this is solved: the listeners declared in Foo will work in ViewController'e Foo , and those declared in Bar - in ViewController'e Bar . 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 () { // ... grid ... } }); refs or some other way to get the component. All technicians require you to give a recognizable property to a table in order to uniquely identify it. Older technicians used the id (and Ext.getCmp ) Ext.getCmp or itemId (using refs or another selection method). The advantage of id is quick sampling, but because identifiers must be unique in the entire application and in the DOM, this is not always achievable. Using itemId and different types of queries (query) is more flexible, but you need to perform a search to find the desired component.reference config in Ext JS 5, we simply add it to the table and use the lookupReference to get 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'); } }); itemId = 'fooGrid' and further this.down('#fooGrid') . But "under the hood" the difference is significant. First, the reference config requires the component to register itself with the owner-view. Secondly, the lookupReference method asks the cache about the need to update (suppose, due to the addition or removal in the container). If everything is fine, it simply returns the link from the cache. In pseudocode: lookupReference: (reference) { var cache = this.references; if (!cache) { Ext.fixReferences(); // cache = this.references; // } return cache[reference]; } reference and listeners configs connect the view only with its ViewController. Nested views can use any reference values ​​within the current one, knowing that these names will not be open to the view that is higher in the hierarchy.listeners requested from the corresponding ViewController and cannot be processed in other controllers with incorrect selectors. Considering that listeners are more preferable than selectors, these two mechanisms can work simultaneously in those places when the use of a selector-based approach is justified.fireViewEvent : fireViewEvent . For example: 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 record = new MyApp.model.Thing(); var grid = this.lookupReference('fooGrid'); grid.store.add(record); this.fireViewEvent('addrecord', this, record); } }); Ext.define('MyApp.view.bar.Bar', { extend: 'Ext.panel.Panel', xtype: 'bar', controller: 'bar', items: [{ xtype: 'foo', listeners: { collapse: 'onCollapse', addrecord: 'onAddRecord' } }] }); fireViewEvent allows fireViewEvent to raise an event for a view inside a ViewController. That is, if in this case there were no ViewControllers, it would be equivalent to calling the usual fireEvent in the “Foo” view code.component has full support for component selectors, while others are limited.view . This event domain allows ViewControllers to use standard methods of listen and control , while implicitly limiting their scope to their own views. He also adds a new special selector to match his own view: Ext.define('MyApp.view.foo.FooController', { extend: 'Ext.app.ViewController', alias: 'controller.foo', control: { '#': { // collapse: 'onCollapse' }, button: { click: 'onAnyButtonClick' } } }); button coincides with any button in this view or in any nested, it does not matter, even in the sub-sub-nested. In other words, handlers based on selectors do not consider inheritance boundaries. This behavior is the same as the previous Ext.app.Controller behavior and in some situations it can be a useful technique.component for processing in Ext.app.Controller controllers.initConfig or its constructor is initConfig .initComponent method has completed in the initComponent . This is a typical time to perform controller initialization, the view of which has already been initialized.callParent ).Source: https://habr.com/ru/post/224645/
All Articles