`
pursue_excellence
  • 浏览: 12591 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Ext架构分析

阅读更多
Ext架构分析(1)--理解Ext.util.Event
原文链接  http://webtec.blog.ccidnet.com/blog-htm-do-showone-uid-77419-type-blog-itemid-246149.html

  由于Ext2.0中所有的组件都是由Observable继承而来,理解Ext就需要先从Ext.util.Observable说起,而Observable是对Event对象进行管理,从而理解Observable必须首先从Ext.util.Event说起。
  Ext.util.Event是一个封装的非常精致的对象,但和你想象的不同,Event同任何的HTML DOM元素没有任何的关系(尽管Ext是处理HTML元素的),实际上,它是一个通用的事件及其事件的处理的对象。 也许有朋友要问,HTML Element本身已经支持了事件,为什么还要再重新设计一套Event机制呢?其实,基本上所有的javascript框架都会实现自己的Event机制,原因很多,但是至少有一点:HTML元素对于事件的处理是通过简单的单一绑定实现,也就是说,如果不进行任何的封装,你的事件只能唯一的绑定到一个事件处理句柄,举个例子:
  var e=document.getElementById("test");
  e.onclick=function(){alert("handle1")};
  e.onclick=function(){alert("handle2")};
  运行的结果你回发现,只会弹出一个"handle2"的alert框,因为第一个事件已经被第二个事件重载了。而使用Ext框架,你可以放心的解决这个问题,同一个事件可以依次被绑定到多个事件处理句柄上。
  Ext.util.Event对象构建器需要传入两个对象:obj(处理事件的缺省对象),name(事件名称)。在构建Event对象时,Event对象会同时构建一个事件的处理函数的数组:listeners,通过这个数组实现了一个事件的多个事件句柄函数的处理。
Ext.util.Event = function(obj, name){
  this.name = name;
  this.obj = obj;
  this.listeners = [];
};

通过Event的fire方法就可以依次触发该数组中的处理函数。 实际上,fire方法在遍历listeners数组中的处理函数过程中,只要处理函数的返回值为false,则不再继续运行后续的处理函数。所以,可以通过检查fire方法的返回值得知事件处理函数是否完全被运行。
  fire : function(){
    var ls = this.listeners, scope, len = ls.length;
    if(len > 0){
      this.firing = true;//通过firing可以保证多个事件处理函数不会并发运行
      var args = Array.prototype.slice.call(arguments, 0);//slice方法可以有效的进行数组的克隆
      for(var i = 0; i < len; i++){
        var l = ls;
        //事件的处理,只要有一个处理函数返回false,整个事件处理就被停止
        if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
          this.firing = false;
          return false;
        }
      }
      this.firing = false;
    }
    return true;
  }

  Event可以通过addListener、removeListener、clearListeners(移除所有的事件处理函数)方法对 listeners进行管理。但是,Listener中保存的事件处理函数实际上并不是addListener传递的函数,实际上,addListener传入的方法通过createListener对事件的处理函数进行了封装,通过封装,实现了对通一个重复事件的的三种不同处理方式:delay(延迟运行)、single(移除Listener中的处理函数,仅运行当前的处理函数)、buffer(避免重复运行处理函数)。
  createListener : function(fn, scope, o){
    o = o || {};
    scope = scope || this.obj;
    var l = {fn: fn, scope: scope, options: o};
    var h = fn;
    if(o.delay){
      h = createDelayed(h, o, scope);
    }
    if(o.single){
      h = createSingle(h, this, fn, scope);
    }
    if(o.buffer){
      h = createBuffered(h, o, scope);
    }
    l.fireFn = h;
    return l;
  }


  var createBuffered = function(h, o, scope){
    var task = new Ext.util.DelayedTask();
    return function(){
        task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
    };
  };
  var createSingle = function(h, e, fn, scope){
    return function(){
        e.removeListener(fn, scope);
        return h.apply(scope, arguments);
    };
  };
  var createDelayed = function(h, o, scope){
    return function(){
        var args = Array.prototype.slice.call(arguments, 0);
        setTimeout(function(){
          h.apply(scope, args);
        }, o.delay || 10);
    };
  };

Ext架构分析(2)--理解Ext.util.Observable

  Observable维护了一个events数组,并提供了更加方便的对于事件的封装和调用机制。同Event一样,它也提供了addListener、 removeListener方法。它提供的addListenere方法使用起来更加方便,你可以通过json对象一次实现多个事件的绑定:
foo.addListener({
'click' : {
  fn: this.onClick,
  scope: this,
  delay: 100
},
'mouseover' : {
  fn: this.onMouseOver,
  scope: this
},
'mouseout' : {
  fn: this.onMouseOut,
  scope: this
}
})

如果你看一下源程序,你会发现,实际上,observable最终还是把事件绑定机制委托到Event对象上:
addListener : function(eventName, fn, scope, o){
    //如果参数是一个json对象
    if(typeof eventName == "object"){
    o = eventName;
    for(var e in o){
      if(this.filterOptRe.test(e)){
        continue;
      }
      if(typeof o[e] == "function"){
        // shared options
        this.addListener(e, o[e], o.scope, o);
      }else{
        // individual options
        this.addListener(e, o[e].fn, o[e].scope, o[e]);
      }
    }
    return;
  }
  o = (!o || typeof o == "boolean") ? {} : o;
  eventName = eventName.toLowerCase();
  var ce = this.events[eventName] || true;
  if(typeof ce == "boolean"){
    //事件不存在则新建一个Event对象并把它纳入event数组
    ce = new Ext.util.Event(this, eventName);
    this.events[eventName] = ce;
  }
  //调用event的addListener方法
  ce.addListener(fn, scope, o);
}
除了支持addListener方法,Obserable还提供了一个addEvent方法,通过该方法,Observable可以绑定多个不包含处理句柄的Event对象:
  addEvents : function(o){
    if(!this.events){
        this.events = {};
    }
    if(typeof o == 'string'){
        for(var i = 0, a = arguments, v; v = a; i++){
          if(!this.events[a]){
            o[a] = true;
          }
        }
    }else{
        Ext.applyIf(this.events, o);
    }
  },


为了方便使用,observable对addListener和removeListener提供了一个更加简洁的所写:on和un:
Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;
Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;

你可以通过suspendEvents和resumeEvents方法随时对于事件进行暂停和继续:
suspendEvents : function(){
  this.eventsSuspended = true;
},
resumeEvents : function(){
  this.eventsSuspended = false;
},

当然,通过fireEvent方法,你可以触发制定的事件:
fireEvent : function(){
  if(this.eventsSuspended !== true){
    //arguments[0]就是你需要触发的事件
    var ce = this.events[arguments[0].toLowerCase()];
    if(typeof ce == "object"){
      return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
    }
  }
  return true;
},


Observable还通过capture和releaseCapture提供了对于事件处理函数的拦截机制:
Ext.util.Observable.capture = function(o, fn, scope){
o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
};
Ext.util.Observable.releaseCapture = function(o){
o.fireEvent = Ext.util.Observable.prototype.fireEvent;
};

Ext架构分析(3)--Widget之父Component:总结

在这里,我们引用Ext Overview中的Component life cycle对组件的功能进行相应的总结:

配置项对象生效:
组件对象的构造器会把全部的配置项传入到其子类中去,并且进行下列所有的步骤。
组件的底层事件创建
这些事件由组件对象负责触发。事件有enable, disable, beforeshow, show, beforehide, hide, beforerender, render, beforedestroy, destroy
组件在组件管理器里登记
initComponent这方法总是使用在子类中,就其本身而论,该方法是一个模板方法(template method),用于每个子类去现实任何所需的构造器逻辑(any needed constructor logic)。首先会创建类,然后组件对象各层次里面的每个类都应该调用superclass.initComponent。通过该方法,就可方便地实现(implement),或重写(Override)任意一层构造器的逻辑。
加载插件(如果有的话)
如果该组件有指定任何插件,这时便会初始化。
渲染组件(如果必须的话)
如果指定了组件的renderTo 或 applyTo配置属性,那么渲染工作就会立即开始,否则意味着延时渲染(在layout对象的layout方法中也会对组件进行渲染),即等待到显式控制显示,或是其容器告知其显示的命令。

渲染过程 Rendering
触发beforerender事件
这是个可取消的事件,指定的句柄(handler)通过返回false可阻止组件进行渲染
设置好容器
如果没有指定一个容器,那么将使用位于DOM元素中组件的父节点作为容器。
调用onRender方法 这是子类渲染最重要的一个步骤,由于该方法是一个模板方法(template method),用于每个子类去现实任何所需的渲染逻辑(any needed render logic)。首先会创建类,然后组件对象各层次里面的每个类都应调用superclass.onRender。通过该方法,就可方便地实现(implement),或重写(Override)任意一层渲染的逻辑。
处理组件是“隐藏”状态 默认下,许多组件是由CSS样式类如"x-hidden"设置隐藏的。如果 autoShow所配置的值为true,这时就不会有这个"hide"样式类作用在该组件上
自定义的类、样式生效 Custom class and/or style applied
一切组件的子类都支持cls和style 两种特殊的配置属性,分别用于指定用户自定义的CSS样式类和CSS规则。 推荐指定cls的方法来制定组件及其各部分的可视化设置。由于该样式类会套用在组件markup最外的一层元素,所以标准CSS规则会继承到组件下任何子元素的身上。
触发render事件 The render event is fired
这是组件通知成功渲染的一个步骤。这时,你可肯定地认为组件的DOM元素是可用的了。如果尝试在渲染之前访问组件,会抛出一个不可用的异常。
调用了afterRender方法 The afterRender method is called
这是另外一个实现或重写特定所需的“后渲染”逻辑的模板方法。每个子类应调用superclass.afterRender.
组件被隐藏或禁用(如果有的话) The Component is hidden and/or disabled (if applicable)
配置项hidden和disabled到这步生效
所有状态感知的事件初始化(如果有的话) Any state-specific events are initialized (if applicable)
状态感知的组件可由事件声明特殊加载和保存状态。如支持,加入此类的事件。
分享到:
评论

相关推荐

    Linux EXT4文件系统分析.pdf

    Linux EXT4文件系统分析.pdf

    Ext+JS源码分析与开发实例宝典.part4.rar

    Ext+JS源码分析与开发实例宝典.pdf...全面剖析Ext JS 3.0的架构原理 透彻体悟Ext JS的代码之美 讲解近70个DEMO实例 配套DVD中包窗大量源码和案例文件 (另请下载 Ext+JS源码分析与开发实例宝典_光盘源码.part1, part2)

    Ext+JS源码分析与开发实例宝典.part6.rar

    Ext+JS源码分析与开发实例宝典.pdf...全面剖析Ext JS 3.0的架构原理 透彻体悟Ext JS的代码之美 讲解近70个DEMO实例 配套DVD中包窗大量源码和案例文件 (另请下载 Ext+JS源码分析与开发实例宝典_光盘源码.part1, part2)

    EXT安装包4.2.1-1

    4. **强大的图表库**:EXT包含一个完整的图表组件,可以生成各种统计和数据分析图表,如折线图、柱状图、饼图等。 5. **触摸支持**:EXT4.2.1优化了对触摸设备的支持,使得在平板电脑和智能手机上也能流畅操作。 6. ...

    Ext+JS源码分析与开发实例宝典.part2.rar

    Ext+JS源码分析与开发实例宝典.pdf...全面剖析Ext JS 3.0的架构原理 透彻体悟Ext JS的代码之美 讲解近70个DEMO实例 配套DVD中包窗大量源码和案例文件 (另请下载 Ext+JS源码分析与开发实例宝典_光盘源码.part1, part2)

    Ext+JS源码分析与开发实例宝典.part5.rar

    Ext+JS源码分析与开发实例宝典.pdf...全面剖析Ext JS 3.0的架构原理 透彻体悟Ext JS的代码之美 讲解近70个DEMO实例 配套DVD中包窗大量源码和案例文件 (另请下载 Ext+JS源码分析与开发实例宝典_光盘源码.part1, part2)

    Ext+JS源码分析与开发实例宝典.part3.rar

    Ext+JS源码分析与开发实例宝典.pdf...全面剖析Ext JS 3.0的架构原理 透彻体悟Ext JS的代码之美 讲解近70个DEMO实例 配套DVD中包窗大量源码和案例文件 (另请下载 Ext+JS源码分析与开发实例宝典_光盘源码.part1, part2)

    Ext+JS源码分析与开发实例宝典.part1.rar

    Ext+JS源码分析与开发实例宝典.pdf...全面剖析Ext JS 3.0的架构原理 透彻体悟Ext JS的代码之美 讲解近70个DEMO实例 配套DVD中包窗大量源码和案例文件 (另请下载 Ext+JS源码分析与开发实例宝典_光盘源码.part1, part2)

    Ext4研究与性能分析

    - **文件系统结构**:了解Ext4文件系统的总体架构及其组成部分,如超级块(superblock)、inode表、块组等。 - **日志记录机制**:探究Ext4如何实现日志记录,以及不同日志模式对性能的影响。 - **性能分析**:评估...

    Ext JS 4 Architecture

    Ext JS 4在架构层面体现了高度的模块化和可扩展性,这也是它区别于其他前端框架的一个显著特征。以下是关于Ext JS 4架构的详细知识点解析。 1. **架构图说明** Ext JS 4的架构设计允许开发者利用其丰富的组件库和...

    深入浅出ext js源码

    这部分内容可能涵盖了EXT JS的基本架构,包括核心类、事件处理、组件系统等关键模块。 `ext-2.1-tutorial-2009-03-19.rar`可能是EXT JS 2.1版本的教程资料,包含了该版本的示例代码和练习,这对于学习EXT JS的历史...

    Ext4案例大全

    - **日志式文件系统**:Ext4采用日志式架构,保证了在系统崩溃后的恢复能力。 3. **学习案例**: - **创建和格式化Ext4文件系统**:学习如何使用`mkfs.ext4`命令创建新的Ext4分区。 - **挂载和卸载**:了解`...

    EXT 自定义控件扩展

    EXT是一个强大的JavaScript库,主要用于构建富客户端的Web应用程序,其核心理念是提供一套完整的MVC(Model-View-Controller)架构,便于开发复杂的、数据驱动的用户界面。 EXT控件是EXT框架的基础,它们提供了丰富...

    Linux Ext2fs文件系统分析.pdf

    Linux Ext2fs文件系统分析.pdf

    EXT/C# 酒店管理系统

    7. **报表与数据分析**:酒店管理系统可能包含报表功能,使用EXT JS的图表组件展示经营数据,如入住率、收入分析等。这需要后端提供聚合查询并支持数据导出。 8. **异常处理与日志记录**:为了确保系统的稳定性和可...

    grid js 例子一个 ext 的

    - **Ext JS 的架构**:了解 Ext JS 的整体架构有助于更好地掌握其使用方法。 - **样式定制**:可以通过自定义 CSS 来调整 Grid 的外观。 - **事件处理**:掌握如何为 Grid 添加事件监听器,例如点击行时触发的操作。...

    ext js中文开发手册

    源码分析涉及组件架构、事件处理流程、数据绑定机制等方面,对于定制高级功能和调试问题尤为重要。 **九、程序规划入门** 在使用EXT JS进行项目开发前,合理的规划至关重要。这包括选择合适的布局、定义组件层次、...

    EXT 的一个例子lookup

    深入学习EXT的`lookup`机制,不仅需要理解EXT的基础组件和数据模型,还需要熟悉其事件驱动和MVC架构。通过阅读和分析给定的JavaScript文件,开发者可以更好地理解和实现这样的功能。同时,Google和EXT的官方文档是很...

    EXT 树形结构样例

    EXT Tree在Web应用中广泛使用,特别是在需要展示层级关系数据的场景下,如文件系统、组织架构或导航菜单。这个"EXT 树形结构样例"提供了使用JSON格式返回数据类型的具体示例,帮助开发者理解如何有效地构建和操作EXT...

Global site tag (gtag.js) - Google Analytics