组件-Components

Ext JS应用界面由许多的部件组成,成为组件(Components)。所有组件都继承自Ext.Component 类,能够自动化管理其生命周期,包括:实例化(instantiation)、渲染(rendering)、调整尺寸(sizing )、定位(positioning)和销毁(destruction)。Ext JS提供了大量非常有用的组件,而且所有组件都可以被继承和扩展,用于开发自定义的组件。

组件层次结构-The Component Hierarchy

容器是一种特殊类型的组件,它可以包含其他组件。典型的应用是由多级嵌套(类似树型结构)的组件组成。容器负责管理其子组件的生命周期,包括创建、渲染、尺寸和定位以及销毁。典型应用的组件层次结构的顶层是Viewport,包含其他的容器或组件:

子组件通过容器的items属性配置添加到容器。下面示例使用 Ext.create()方法创建了两个Panel,然后将其添加到Viewport:

var childPanel1 = Ext.create('Ext.panel.Panel', {
    title: 'Child Panel 1',
    html: 'A Panel'
});

var childPanel2 = Ext.create('Ext.panel.Panel', {
    title: 'Child Panel 2',
    html: 'Another Panel'
});

Ext.create('Ext.container.Viewport', {
    items: [ childPanel1, childPanel2 ]
});

XTypes和延迟初始化-XTypes and Lazy Instantiation

组件有个xtype象征性名称。例如:Ext.panel.Panel的xtype为panel。上述示例演示的是将两个已经实例化的组件添加到容器中。对于一个大型应用来说,并非所有组件都需要立即实例化,根据应用的使用情况,有些组件可能永远都未实例化。例如,一个应用使用 Tab Panel展现信息,只有当用户点击某个标签页(Tab)后,才需要渲染该标签的内容。这时就可以使用xtype属性先将组件添加到容器,直到容器认为有必要的时候再实例化。

下面的示例用Tab Panel演示了组件的延迟实例化和渲染,每个标签页有个render事件处理,提示该组件已被渲染。

Ext.create('Ext.tab.Panel', {
    renderTo: Ext.getBody(),
    height: 100,
    width: 200,
    items: [
        {
            // Explicitly define the xtype of this Component configuration.
            // This tells the Container (the tab panel in this case)
            // to instantiate a Ext.panel.Panel when it deems necessary
            xtype: 'panel',
            title: 'Tab One',
            html: 'The first tab',
            listeners: {
                render: function() {
                    Ext.MessageBox.alert('Rendered One', 'Tab One was rendered.');
                }
            }
        },
        {
            // xtype for all Component configurations in a Container
            title: 'Tab Two',
            html: 'The second tab',
            listeners: {
                render: function() {
                    Ext.MessageBox.alert('Rendered One', 'Tab Two was rendered.');
                }
            }
        }
    ]
});

运行上述示例,第一个标签页立即提示了渲染信息,如果点击了第二个标签页,第二个标签页才会被渲染并提示信息。

显示和隐藏-Showing and Hiding

所有组件都有showhide 方法。隐藏组件缺省使用 CSS样式display: none的方式处理,但是可以通过hideMode配置进行设置:

var panel = Ext.create('Ext.panel.Panel', {
    renderTo: Ext.getBody(),
    title: 'Test',
    html: 'Test Panel',

    // use the CSS visibility property to show and hide this component
    hideMode: 'visibility' 
});

panel.hide(); // hide the component
panel.show(); // show the component

浮动组件-Floating Components

浮动组件使用CSS的绝对定位,不受文档流和容器的布局限制。一些组件(例如:Window)缺省就是浮动的,通过floating配置可以将其他组件设置为浮动的。

var panel = Ext.create('Ext.panel.Panel', {
    width: 200,
    height: 100,
    // make this panel an absolutely-positioned floating component
    floating: true,
    title: 'Test',
    html: 'Test Panel'
});

上述示例实例化了一个Panel,但是没有渲染它。通常情况下,组件或者配置renderTo的属性,或者作为子组件添加到某个容器,但是对于浮动组件来说是不需要的。浮动组件只有第一次调用其show的方法时才会自动渲染到文档中:

// render and show the floating panel
panel.show();

还有一些与浮动组件相关的配置或方法:

  • draggable - 允许在屏幕上拖拽组件;
  • shadow - 定制浮动组件的阴影样式;
  • alignTo() - 将浮动组件对齐到某个元素;
  • center() -将浮动组件在容器内居中显示;

自定义组件-Creating Custom Components

创作或扩展-Composition or Extension

在创建自定义组件时,需要考虑该组件是一个组件的实例还是扩展了一个组件。建议根据功能需求扩展最适合的组件,可以利用Ext JS框架提供的功能自动管理组件的生命周期,这比手动管理一个组件的生命周期更容易。

子类化-Subclassing

Ext JS的类管理体系可以很容易地扩展其框架。Ext.Base是所有Ext JS类的基类,所有类都继承了该类的原型(prototype)和静态成员(static members)。虽然可以从最底层的 Ext.base继承开发自定义的功能,但是大多数场景下,更适合从较高层次的类继承。下述示例创建了一个Ext.Component的子类:

Ext.define('My.custom.Component', {
    extend: 'Ext.Component',

    newMethod : function() {
       //...
    }
});

该示例创建了一个新的组件类,继承了Ext.Component的所功能(属性、方法等),并添加一些自己的属性或方法。

模板方法模式-Template Methods

Ext JS使用模板方法模式代理子类的行为。这意味着继承链上的每个子类,在其生命周期内的一定阶段都可以添加自己的处理逻辑。例如render功能。render是组件定义的方法,负责组件生命周期的初始渲染阶段。render不能被重载,但是在渲染过程中调用onRender方法,允许子类实现该方法并添加自己的处理。每个子类的onRender方法必须调用其父类superclassonRender方法从而实现逻辑的扩展。下图说明了onRender模板方法的功能:

下面的示例演示了组件的一个子类实现onRender的方法:

Ext.define('My.custom.Component', {
    extend: 'Ext.Component',
    onRender: function() {
        // call the superclass onRender method
        this.callParent(arguments); 

        // perform additional rendering tasks here.
    }
});

值得注意的是,大多数的模板方法都有一个对应的事件。例如当组件渲染后将触发render事件。当子类化时,基本上要使用模板方法处理自定义的逻辑,而不是使用事件处理。事件有可能被挂起(suspended)或者被事件处理器终止。

下面列出的是可以被 Ext.Component 类的子类实现(implement)的模板方法:

  • initComponent :该方法由构造函数调用。用于初始化数据(initialize data),设置配置项(set up configuration),以及绑定事件处理(attach event handlers)。
  • beforeShow :该方法在组件显示前调用。
  • onShow :允许为显示操作添加扩展行为。调用父类的 onShow 方法后,组件将被显示。
  • afterShow :组件显示后调用此方法。
  • onShowComplete :该方法在组件的 afterShow 方法处理完成后调用。
  • onHide :允许为隐藏操作添加扩展行为。调用父类的 onHide 方法后,组件将被隐藏。
  • afterHide :组件隐藏后调用此方法。
  • onRender :允许在渲染阶段添加扩展行为。
  • afterRender :允许在渲染结束后添加扩展行为。在这个阶段,组件的元素已经根据配置信息进行了样式处理,添加了 CSS 类名,处于配置的可见和可用状态。
  • onEnable :允许为可用操作添加扩展行为。调用父类的 onEnable 方法后,组件将可用。
  • onDisable :允许为禁用操作添加扩展行为。调用父类的 onDisable 方法后,组件将禁用。
  • onAdded :允许为组件添加到容器后添加扩展行为。在这个阶段,组件添加到父容器的子组件集合,调用父类的 onAdded 方法后,组件的 ownerCt 才可用。如果配置了 ref ,那么 refOwner 将被赋值。
  • onRemoved :允许为组件从父容器中移除后添加扩展行为。在这个阶段,组件从父容器的子组件集合中移除,但是还没有被销毁(如果父容器的 autoDestroy 配置为 true,或者调用 remove 方法时第二个参数传递了 true ,那么该组件将被销毁)。调用父类的onRemoved 方法后,组件的 ownerCtrefOwner 都将被清除。
  • onResize :允许为调整尺寸的操作添加扩展行为。
  • onPosition :允许为定位的操作添加扩展行为。
  • onDestroy :允许为销毁操作添加扩展行为。调用父类的onDestroy 方法后,该组件将被销毁。
  • beforeDestroy :该方法在组件被销毁前调用。
  • afterSetPosition :该方法在组件被设置位置后调用。
  • afterComponentLayout :该方法在组件设置完布局后调用。
  • beforeComponentLayout :该方法在组件设置布局前调用。

扩展哪个类-Which Class To Extend

选择最合适的类进行扩展是非常重要的事情,同时还要考虑基类必须提供哪些功能。当UI组件需要被渲染和管理时,倾向于选择 Ext.panel.Panel 进行扩展。

Panel 类具备很多能力:

  • 边框(Border)
  • 标题行(Header)
  • 标题行工具(Header tools)
  • 状态栏(Footer)
  • 状态栏按钮(Footer buttons)
  • 顶端工具栏(Top toolbar)
  • 底端工具栏(Bottom toolbar)
  • 包含和管理子组件

如果不需要这些功能,那么选择Panel将浪费资源。

Component类

如果需求的UI组件不需要包含其他的组件,也就是说它只是封装一些HTML元素,那么适合从 Ext.Component 类扩展。例如下面示例的类封装了HTML的image元素,允许设置元素的src属性。而且在图片加载后触发一个load事件:

该示例只是用于演示,实际应用应该使用 Ext.Img

Ext.define('Ext.ux.Image', {
    // subclass Ext.Component
    extend: 'Ext.Component', 

    // this component will have an xtype of 'managedimage'
    alias: 'widget.managedimage', 

    autoEl: {
        tag: 'img',
        src: Ext.BLANK_IMAGE_URL,
        cls: 'my-managed-image'
    },

    // Add custom processing to the onRender phase.
    // Add a 'load' listener to the element.
    onRender: function() {
        this.autoEl = Ext.apply({}, this.initialConfig, this.autoEl);
        this.callParent(arguments);
        this.el.on('load', this.onLoad, this);
    },

    onLoad: function() {
        this.fireEvent('load', this);
    },

    setSrc: function(src) {
        if (this.rendered) {
            this.el.dom.src = src;
        } else {
            this.src = src;
        }
    },

    getSrc: function(src) {
        return this.el.dom.src || this.src;
    }
});

上述类的用法:

var image = Ext.create('Ext.ux.Image');

Ext.create('Ext.panel.Panel', {
    title: 'Image Panel',
    height: 200,
    renderTo: Ext.getBody(),
    items: [ image ]
});

image.on('load', function() {
    console.log('image loaded: ', image.getSrc());
});

image.setSrc('http://www.sencha.com/img/sencha-large.png');

Container类

如果需求的UI组件需要包含其他组件,但是不需要Panel的那些特殊功能,那么适合从 Ext.container.Container 类扩展。请切记:在容器这个层次的组件是使用 Ext.layout.container.Container 布局系统渲染和管理子组件的。

Container类具有下列的模板方法:

  • onBeforeAdd :在添加一个子组件之前调用该方法。该方法接收的参数有要添加的组件,适用于修改要添加的组件,或者以某种方式准备容器。如果返回false将取消添加操作。
  • onAdd :在添加了一个子组件后调用该方法。该方法接收的参数有已添加的组件。该方法可以用于根据子组件的状态更新内部的结构。
  • onRemove :在移除了一个子组件后调用该方法。该方法接收的参数有被移除的组件。该方法可用于根据子组件的状态更新内部的结构。
  • beforeLayout :在容器完成子组件布局之前(如果需要,可以完成渲染)调用该方法。
  • afterLayout :在容器完成子组件布局之后(如果需要,可以完成渲染)调用该方法。

Panel类

如果需求的UI组件必须具有标题行、状态栏、工具栏,那么适合从Ext.panel.Panel 类扩展。

注意: Panel 是一个容器。 要切记使用那个布局管理子组件。

Ext.panel.Panel 扩展的类通常是较高应用层级的特定组件,一般用于以配置的布局管理其他的UI组件(容器或者表单域),并通过tbarbbar组件提供的操作控件,管理和操作内部的组件。

Panel类具有下列的模板方法:

  • afterCollapse :当Panel被收起(Collapsed)后调用该方法。
  • afterExpand :当Panel被展开(Expanded)后调用该方法。
  • onDockedAdd :当一个Docked组件添加到Panel后调用该方法。
  • onDockedRemove :当一个Docked组件从Panel移除后调用该方法。

results matching ""

    No results matching ""