将 ExtJS MVC 控制器附加到 DOM 元素,而不是组件 [英] Attach ExtJS MVC controllers to DOM elements, not components

查看:18
本文介绍了将 ExtJS MVC 控制器附加到 DOM 元素,而不是组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我试过了

Ext.define('app.controller.TabController', {扩展:'Ext.app.Controller',初始化:函数(){控制台日志(初始化");this.control({'一个': {点击:this.changeTab}});},更改选项卡:函数(){警报(新标签!");}});

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

有没有办法用 this.control 指定一个 CSS 选择器?还是只适用于组件?

解决方案

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

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

最终目标是只有您的视图应该关注界面事件和 DOM 元素等内容,而应用程序级控制器只处理有意义的用户意图.您的应用程序和控制器代码根本不应与您的标记结构或接口实现耦合.

示例视图

Ext.define('MyApp.view.UserGallery', {扩展:'Ext.Component',xtype: '用户画廊',tpl: '<tpl for="users"><img src="{avatar_src}" data-ID="{id}"></tpl>',initComponent: 函数() {this.addEvents('userselected');this.callParent(参数);},afterRender: 函数() {this.mon(this.el, 'click', this.onUserClick, this, {delegate: 'img'});this.callParent(参数);},onUserClick: 函数(ev, t) {ev.stopEvent();var userId = Ext.fly(t).getAttribute('data-ID');this.fireEvent('userselected', this, userId, ev);}});

关于视图的说明

  • 当您只需要一个托管的

    时,扩展Ext.Component",Ext.Panel 更重,可以支持标题栏、工具栏、折叠等内容.
  • 在组件中将侦听器附加到 DOM 元素时使用托管"侦​​听器(请参阅 Component.mon).组件管理的监听器会在组件被销毁时自动释放
  • 从多个 DOM 元素侦听同一事件时,请使用委托"事件选项并将侦听器附加到它们的公共父元素而不是单个元素.这表现得更好,让您可以任意创建/销毁子元素,而不必担心不断地为每个子元素附加/删除事件侦听器.避免使用类似 .select('img').on('click', handler)
  • 当从视图触发事件时,Sencha 的约定是事件的第一个参数是 scope -- 对触发事件的视图的引用.当从控制器处理事件时,这很方便,您需要事件处理程序的实际范围作为控制器.

样品控制器

Ext.define('app.controller.myController', {扩展:'Ext.app.Controller',init: 函数() {this.control({'用户画廊':{用户选择:函数(galleryView,userId,ev){this.openUserProfile(userID);}}});},openUserProfile: 函数(用户 ID){alert('在此处加载另一个视图');}});

Is there a way to use the Ext.app.Controller control() method, but pass in a DOM query? I have a page that contains standard links and would like to add a click handler to them even though they were not created as Ext Buttons.

I've tried

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!");
    }   
});

But clicking on links does not fire the alert.

Is there a way to specify a CSS selector with this.control? Or does it only work with components?

解决方案

I asked this question at SenchaCon this year, the Sencha developers stated that their intent is that DOM listeners should be attached within your view, and the view should abstract them into more meaningful component events and refire them.

For example, suppose you're creating a view called UserGallery that shows a grid of people's faces. Within your UserGallery view class, you would listen for the DOM click event on the <img> tag to receive event and target, and then the view might fire a component event called "userselected" and pass the model instance for the clicked user instead of the DOM target.

The end goal is that only your views should be concerned with things like interface events and DOM elements while the application-level controller only deals with meaningful user intents. Your application and controller code shouldn't be coupled to your markup structure or interface implementation at all.

Sample View

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);
    }
});

Notes on views

  • Extend "Ext.Component" when all you want is a managed <div>, Ext.Panel is a lot heavier to support things like titlebars, toolbars, collapsing, etc.
  • Use "managed" listeners when attaching listeners to DOM elements from a component (see Component.mon). Listeners managed by a components will be automatically released when that component gets destroyed
  • When listening for the same event from multiple DOM elements, use the "delegate" event option and attach the listener to their common parent rather than to individual elements. This performs better and lets you create / destroy child elements arbitrarily without worrying about continuously attaching/removing event listeners to each child. Avoid using something like .select('img').on('click', handler)
  • When firing an event from a view, Sencha's convention is that the first parameter to the event be scope -- a reference to the view that fired the event. This is convenient when the event is being handled from a controller where you'll need the actual scope of the event handler to be the controller.

Sample Controller

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');
    }
});

这篇关于将 ExtJS MVC 控制器附加到 DOM 元素,而不是组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆