代码改变世界

初学Ext UI组件总结及(一)-- >读Ext.Component源码学习笔记

2012-02-13 23:11    阅读(349)  评论(0)    收藏  举报

为了可以缓解审美疲劳,写出自己的Ext UI组件,加油。

错误之处,请大家指出。

Ext.Component是所有UI组件的顶层类,它继承了Observable,以支持高级语义事件。

ExtUI组件的生命周期,粗略可分为,初始化组件-->渲染组件-->销毁组件

Ext.Component有点“模板模式”的味道,它不能“布局”也不能“show”出来,它只是定义了所有UI组件的“生老病死”和实现了一些通用的逻辑,然而每个组件的初始化过程渲染过程都不尽相同,所以具体的实现推迟到不同的子类中实现。

源码片段一(构造函数中)

   

config构造参数的

   config = config || {};

    //传特殊参数的处理

    if(config.initialConfig){

        if(config.isAction){           // actions

            this.baseAction = config;

        }

        config = config.initialConfig;


//容错处理,如果传入的是dom或者是Ext.Element及字符串,那么就根据它生成一个     

//配置项

    }else if(config.tagName || config.dom || Ext.isString(config)){ 

        config = {applyTo: config, id: config.id || config};

    }

    

    this.initialConfig = config;

    //拷贝配置项到"this"

Ext.apply(this, config);

//添加一些语义事件,可以想一下,此层应该对应实现什么事件

 this.addEvents{...}

 //下面二行,对此UI实例进行注册,以便可以借助Ext.ComponentMgr快捷的超找出      //此UI组件

 this.getId();

 Ext.ComponentMgr.register(this);

 //调用父类的构造参数

Ext.Component.superclass.constructor.call(this);

//初始化组件,这个是模板方法,留空,交给子类重写

this.initComponent();

 //这个是插件机制,比较有意思,理解还很浅,有一个“接口”,插件需要实现init()方          法

 if(this.plugins){

        if(Ext.isArray(this.plugins)){

            for(var i = 0, len = this.plugins.length; i < len; i++){

                this.plugins[i] = this.initPlugin(this.plugins[i]);

            }

        }else{

            this.plugins = this.initPlugin(this.plugins);

        }

    }

    //状态管理

    if(this.stateful !== false){

        this.initState();

    }

//渲染,applyTo和renderTo的区别在于插入DOM的位置,但最终依旧是依靠render函数渲染

 if(this.applyTo){

        this.applyToMarkup(this.applyTo);

        delete this.applyTo;

 }else if(this.renderTo){

        this.render(this.renderTo);

        delete this.renderTo;

 }

Ext.extend(Ext.Component, Ext.util.Observable, {..});

//...中,添加的重要实例方法如下

//源码注释:this is double processing, however it allows people to be able to do 

initComponent : function(){

       //在UI继承树顶层的Ext.Component只是绑定了监听器

        if(this.listeners){

            this.on(this.listeners);

            delete this.listeners;

        }

        this.enableBubble(this.bubbleEvents);

    },

//渲染过程,精华所在

render : function(container, position){

     //触发了beforerender事件,不为false才继续渲染,可以写此监听让其返回false阻止其渲染   

     if(!this.rendered && this.fireEvent('beforerender', this) !== false){

          //找到容纳元素的容器  

          if(!container && this.el){

                this.el = Ext.get(this.el);

                container = this.el.dom.parentNode;

                this.allowDomMove = false;

            }

           //很巧妙的一步,把包裹整个UI的最外层,包装成Ext.Element元素,比便可以使用Element的动画,拖拽,及其他工具函数 

           this.container = Ext.get(container);

           //添加容器的层叠样式 

           if(this.ctCls){

                this.container.addClass(this.ctCls);

            }

            

           this.rendered = true;

            if(position !== undefined){

                if(Ext.isNumber(position)){

                    position = this.container.dom.childNodes[position];

                }else{

                    position = Ext.getDom(position);

                }

            }

            

            //子类中需要根据如何渲染重写此方法

            this.onRender(this.container, position || null);

            if(this.autoShow){

                this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);

            }

            if(this.cls){

                this.el.addClass(this.cls);

                delete this.cls;

            }

            if(this.style){

                this.el.applyStyles(this.style);

                delete this.style;

            }

            if(this.overCls){

                this.el.addClassOnOver(this.overCls);

            }

            //触发render事件

            this.fireEvent('render', this);

            

            var contentTarget = this.getContentTarget();

            //根据配置项html,或者tpl'(模板)插入dom内容

            if (this.html){

                contentTarget.update(Ext.DomHelper.markup(this.html));

                delete this.html;

            }

            if (this.contentEl){

                var ce = Ext.getDom(this.contentEl);

                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);

                contentTarget.appendChild(ce);

            }

            if (this.tpl) {

                if (!this.tpl.compile) {

                    this.tpl = new Ext.XTemplate(this.tpl);

                }

                if (this.data) {

                    this.tpl[this.tplWriteMode](contentTarget, this.data);

                    delete this.data;

                }

            }

            //渲染完毕

            //调用afterReader函数

            this.afterRender(this.container);

            if(this.hidden){

                // call this so we don't fire initial hide events.

                this.doHide();

            }

            if(this.disabled){

                // pass silent so the event doesn't fire the first time.

                this.disable(true);

            }

            if(this.stateful !== false){

                this.initStateEvents();

            }

            this.fireEvent('afterrender', this);

        }

        return this;

    },

//真正干渲染工作的方法,需要根据子类重写

 onRender : function(ct, position){

        if(!this.el && this.autoEl){

            if(Ext.isString(this.autoEl)){

                this.el = document.createElement(this.autoEl);

            }else{

                var div = document.createElement('div');

                Ext.DomHelper.overwrite(div, this.autoEl);

                this.el = div.firstChild;

            }

            if (!this.el.id) {

                this.el.id = this.getId();

            }

        }

        if(this.el){

            this.el = Ext.get(this.el);

            if(this.allowDomMove !== false){

                ct.dom.insertBefore(this.el.dom, position);

                if (div) {

                    Ext.removeNode(div);

                    div = null;

                }

            }

        }

    },

  

//组件的销毁

  //删除组件对应的Dom节点

  destroy : function(){

        if(!this.isDestroyed){

            if(this.fireEvent('beforedestroy', this) !== false){

                this.destroying = true;

                //触发销毁之前函数,可以“趁机”做一些工作

                this.beforeDestroy();

                //如果有对应容器,移除

                if(this.ownerCt && this.ownerCt.remove){

                    this.ownerCt.remove(this, false);

                }

                if(this.rendered){

                    this.el.remove();

                    if(this.actionMode == 'container' || this.removeMode == 'container'){

                        this.container.remove();

                    }

                }

                // Stop any buffered tasks

                if(this.focusTask && this.focusTask.cancel){

                    this.focusTask.cancel();

                }

                this.onDestroy();

                //注销组件

                Ext.ComponentMgr.unregister(this);

                this.fireEvent('destroy', this);

                //消除监听

                this.purgeListeners();

                this.destroying = false;

                this.isDestroyed = true;

            }

        }

    },