博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

extJs 2.1学习笔记(Ext.TabPanel篇)

Posted on 2009-07-31 19:55  linFen  阅读(2788)  评论(0编辑  收藏  举报
Ext.TabPanel这个东西是最常用的组件之一,它继承自Ext.Panel。看了一个下午的源代码,对它的一些基本原理有所了解了。

  下面要讲一些问题,这些问题绝对是本人独门秘笈,非入室弟子不传。哈哈哈。

  一、组件的组成:

  因为继承自Ext.Panel,所以,它也是由header、tbar、body、bbar、footer这几个部分构成,有人问:TabPanel的面板标签是在哪儿呢(就是你点击换页的东西)?它默认是放在header中的。但是,如果设置了:tabPosition的话就不一定了,tabPosition可取两个值:top、bottom。所以,标签可以是放在下面,但是,Ext目前还不支技放在左边、右边。

  那么,不同的标签是用什么元素来组织的呢?用ul。一页对应一个li。li的id的取值有规律哦,它的取值公式如下:tabpanel.id+tabpanel.idDelimiter+面板的id。正是因为有了这个规律,才能根据点击的标签而找到对应的面板。这个问题是一大主题,在下面讲。

  这是面板的标签,下面的面板呢?简单!!!一个Ext.Panel对应一个面板,注意:这儿的面板是没有header的,如果你想tab.items.get(1).header,在这儿,header===undefined。为什么为面板定义的title会对应到标签中去呢?这个是TabPanel的特意处理的。至于换页效果是怎么出来的?CardLayout。这下组件的大概结构都清楚了。还有不明白,自己new Ext.TabPanel({……})一个,然后在FireBug下面去查看dom结构,就一清二楚了。

  二、处理标签的事件

  为什么要研究这个问题?有需求的,如何在鼠标移到标签上时就显示对应的面板呢?默认情况下,TabPanel是不支持这个功能的,但是,这个功能有时是需要的。这儿有点小技巧。

  看Ext.TabPanel源代码中关于标签的事件处理:

        this.strip.on('mousedown', this.onStripMouseDown, this);
        this.strip.on('click', this.onStripClick, this);
        this.strip.on('contextmenu', this.onStripContextMenu, this);
        if(this.enableTabScroll){
            this.strip.on('mousewheel', this.onWheel, this);
        }

  这段代码写在initEvents函数中,先解释一下,this.strip是指头部放标签的那个ul元素,相信,98%的读者会想,要注册事件也应当是为li元素注册,怎么会统统注册到ul这个父容器上面呢?原理就是事件冒泡。关于事件传递的原理,本人在下一文中有详细的实验、明确的结论,不再赘言。

  ul元素捕获了事件,怎样在事件处理函数中得知倒底是哪个li发生了事件呢?Ext写了个函数:findTargets。详情请见如下代码:

    findTargets : function(e){
        var item = null;
        var itemEl = e.getTarget('li', this.strip);
        if(itemEl){
            item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
            if(item.disabled){
                return {
                    close : null,
                    item : null,
                    el : null
                };
            }
        }
        return {
            close : e.getTarget('.x-tab-strip-close', this.strip),
            item : item,
            el : itemEl
        };
    },

    // private
    onStripMouseDown : function(e){
        e.preventDefault();
        if(e.button != 0){
            return;
        }
        var t = this.findTargets(e);
        if(t.close){
            this.remove(t.item);
            return;
        }
        if(t.item && t.item != this.activeTab){
            this.setActiveTab(t.item);
        }
    },

  一切的关键就在于li元素的id的命名规则,从中取出对应的面板的id,这样就能getComponent,从而获得对应的面板引用,再setActiveTab就办成了。至于getTarget这个是EventObject中封装的函数,作用是在事件传播路径上查找满足指定选择条件的元素。这个函数的详情见它的源码。

  到了这里,之前所讲的鼠标悬停问题只要依照方面方法解决就是了,切记,不要处理mouseout事件,不然,事情就麻烦了,详情见我以前写过的关于mouseover事件的一篇文章。