将ExtJS MVC控制器附加到DOM元素,而不是组件

Nat*_*and 19 extjs extjs4 extjs-mvc

有没有办法使用Ext.app.Controller control()方法,但传入DOM查询?我有一个包含标准链接的页面,并希望为它们添加一个单击处理程序,即使它们不是作为Ext Buttons创建的.

我试过了

Ext.define('app.controller.TabController', {
    extend: 'Ext.app.Controller',

    init: function() {
        console.log("init");
        this.control({
            'a': {
                click: this.changeTab
            }   
        });
    },

    changeTab: function() {
        alert("new tab!");
    }   
});
Run Code Online (Sandbox Code Playgroud)

但是点击链接不会触发警报.

有没有办法用this.control指定CSS选择器?或者它只适用于组件?

The*_*ris 39

今年我在SenchaCon上问了这个问题,Sencha开发人员表示他们的意图是DOM监听器应该附加在你的视图中,并且视图应该将它们抽象为更有意义的组件事件并重新启用它们.

例如,假设您正在创建一个名为UserGallery的视图,该视图显示人脸的网格.在UserGallery视图类中,您将监听<img>标记上的DOM单击事件以接收事件和目标,然后视图可能会触发一个名为"userselected"的组件事件,并为被点击的用户而不是DOM目标传递模型实例.

最终目标是只有你的视图应该关注接口事件和DOM元素之类的东西,而应用程序级控制器只处理有意义的用户意图.您的应用程序和控制器代码根本不应与您的标记结构或接口实现相关联.

示例视图

Ext.define('MyApp.view.UserGallery', {
    extend: 'Ext.Component'
    ,xtype: 'usergallery'

    ,tpl: '<tpl for="users"><img src="{avatar_src}" data-ID="{id}"></tpl>'

    ,initComponent: function() {
        this.addEvents('userselected');

        this.callParent(arguments);
    }

    ,afterRender: function() {
        this.mon(this.el, 'click', this.onUserClick, this, {delegate: 'img'});

        this.callParent(arguments);
    }

    ,onUserClick: function(ev, t) {
        ev.stopEvent();

        var userId = Ext.fly(t).getAttribute('data-ID');

        this.fireEvent('userselected', this, userId, ev);
    }
});
Run Code Online (Sandbox Code Playgroud)

意见备注

  • 当你想要的只是一个托管的时候扩展"Ext.Component" <div>,Ext.Panel要比标题栏,工具栏,折叠等更重要.
  • 将侦听器附加到组件中的DOM元素时使用"托管"侦​​听器(请参阅Component.mon).当组件被销毁时,由组件管理的监听器将自动释放
  • 从多个DOM元素中侦听同一事件时,请使用"delegate"事件选项并将侦听器附加到其公共父元素而不是单个元素.这样做效果更好,并允许您任意创建/销毁子元素,而无需担心持续连接/删除每个子节点的事件侦听器.避免使用类似的东西.select('img').on('click', handler)
  • 从视图中触发事件时,Sencha的约定是事件的第一个参数是scope- 对触发事件的视图的引用.当从控制器处理事件时,这很方便,您需要将事件处理程序的实际范围作为控制器.

样本控制器

Ext.define('app.controller.myController', {
    extend: 'Ext.app.Controller'

    ,init: function() {
        this.control({
            'usergallery': {
                userselected: function(galleryView, userId, ev) {
                    this.openUserProfile(userID);
                }
            }   
        });
    }

    ,openUserProfile: function(userId) {
        alert('load another view here');
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.这应该在事件指南中. (3认同)