重庆熊猫 Loading

ExtJS-组件(Components)-第一部分

更新记录
2022年7月8日 发布。
2022年6月25日 从笔记迁移到博客。

ExtJS教程汇总:https://www.cnblogs.com/cqpanda/p/16328016.html

组件(Components)第一部分地址:
https://www.cnblogs.com/cqpanda/p/16411858.html
组件(Components)第二部分地址:
https://www.cnblogs.com/cqpanda/p/16411884.html

组件说明

Ext JS应用程序由一个或多个称为组件(Component)的单元组成
所有组件都是Ext.Component类的子类,其提供组件自动生命周期管理
Ext JS提供许多开箱即用的组件,组件可以很容易地扩展以创建自定义组件
ExtJS预定义组件有xtype属性,常用于用于懒加载(lazy load)

组件内部组成

xtype:组件的别名
Hierarchy 层次结构
Inherited mixins 混入的类
Requires 该组件需要使用的类
configs:组件的配置信息
properties:组件的属性
methods:组件的方法
events:组件的事件

组件生命周期(Component Life Cycle)

说明

继承Ext.Component类可以实现使用ExtJS提供的组件自动生命周期管理
ExtJS类自动生命周期管理包括:
初始化(Initialization Process)
渲染(Rendering Process)(呈现、大小调整和定位)
销毁(Destruction Process)
image
初始化阶段将会实例化组件,并将组件加入组件管理器(component manager)
渲染阶段将会创建组件所需要的DOM节点,并添加到document中
销毁阶段将会对组件进行销毁操作,并从DOM中移除节点和事件监听

初始化(Initialization)阶段

初始化阶段就是组件实例化阶段
所有必需的配置设定、事件注册和预渲染过程都在这个阶段
初始化阶段通常是最快的,因为所有工作都是在JavaScript中完成的
组件并不一定要渲染过才能销毁,初始化后就可以进行销毁
image

初始化阶段步骤:
(1) 应用配置
在实例化组件时,传入配置对象
配置对象包含组件实现其功能所必需的全部参数和引用

(2) 注册基础组件事件
根据组件模型,Ext.Component的每个子类都默认拥有一套由基类触发的核心事件
这些事件在以下一些行为发生前后触发:
启用/禁用、显示、隐藏、渲染、销毁、状态还原和状态保存
事件触发后,可以测试是否能够成功返回一个被注册的事件处理程序
并在执行任何实际的操作之前取消该行为
例如:调用myPanel.show时,会触发beforeshow事件执行事件注册的任何方法
如果beforeshow事件处理程序返回false,myPanel就不会显示

(3) 分配或者自动生成组件ID
如果没有为组件配置静态ID
会合并该组件的XType以及从1000开始自动生成的数值,自动生成一个ID
比如:创建一个Ext.panel.Panel实例不配置静态ID
结果该组件就会有一个类似于“panel-1001”的自动生成的ID

(4) 构造预初始化组件插件
执行initComponent方法之前定义的任何插件,都是在这一步构造的
这可以让网格面板编辑器之类的插件在很早的时候就执行某些操作
比如初始化编辑器输入框

(5) 运行initComponent
Component的子类在initComponent方法中执行大量操作
比如注册子类特有事件、引用数据存储以及创建子组件
initComponent被用作对构造器的补充
而且通常被用作扩展Component或者其子类的主要切入点

(6) 注册ComponentManager
每个实例化的组件都通过Ext JS生成的唯一字符串ID
被注册到ComponentManager类
可以选择在传入构造器的配置对象中传入一个id参数来覆盖Ext JS生成的ID
要当心的是,如果用一个非唯一的注册ID发出一个注册请求
则最新的注册将覆盖之前的注册
如果打算使用自己的ID,一定要确保使用唯一的ID

(7) 调用基础混入类构造器
组件利用两个混入类来提供低级别功能
Ext.util.Observable 赋予了组件侦听和触发事件的能力
Ext.state.Stateful则负责为组件处理状态特有事件

(8) 启动调整尺寸状态事件
Component把基础调整尺寸事件注册为一个状态特有事件
这意味着Component的任何子类都有可能感知状态以调整尺寸

(9) 初始化插件
如果在配置对象中把插件传入构造器,插件的Init方法将被调用
而其父 Component将作为引用传入
插件是根据它们被引用的顺序调用的

(10) 引导组件加载器
如果组件是用loader配置属性配置的
那它就被用来构造一个 ComponentLoader的实例
这个类负责通过Ajax为一个组件获取数据
并利用HTML、一个数据或者一个组件渲染器来显示数据

(11) 渲染组件
如果renderTo或者applyTo参数被传入构造器,那渲染阶段就开始了
否则,组件会保持休眠,等待代码或者它的一个父组件调用它的render方法

渲染(Rendering)阶段

image
注意:
如果没有指定renderTo或者applyTo,则要调用render方法,触发该阶段
如果组件不是另一个Ext JS组件的子组件
则代码必须要调用render方法,并传入DOM元素的一个引用
如果该组件是另一个组件的子组件,它的render方法将会被其父组件自动调用
通常来说,组件生命周期的大部分都处于渲染阶段,直到它在销毁阶段消亡
如果初始化因为某种原因失败,那么组件可能不会正确渲染或者根本不会渲染

渲染阶段的各个步骤:
(1) 触发beforerender
组件触发beforerender事件,并且检查任何已注册的事件处理程序的返回值
如果一个已注册的事件处理程序返回false,组件就中止渲染行为
初始化阶段的第二步为Component的子类注册了核心事件
而“before”事件可以中止执行行为

(2) 组件的元素被置入缓存
如果配置了一个带el属性的组件,那它会围绕该元素封装一个 xt.Element的实例

(3) 组件注册为可浮动
如果组件配置为可浮动,它将把自己注册到WindowManager
以启用z-index和焦点管理,这对Window和Menu等类很重要
它们被设计为定位(浮动)于其他UI部件上方

(4) 设置容器
组件需要有容身之处,而这个容身之处就是它的容器
如果指定元素的renderTo配置项
组件就往被引用的元素(也就是它的容器)上添加一个子div 元素
并且在新添加的子元素内部渲染该组件
如果指定元素applyTo的配置项
在applyTo参数中指定的被引用元素就成了组件的容器
而组件只把那些渲染它所需要的元素添加到被引用的元素上
然后该组件对在applyTo中引用的DOM元素就有了完全的管理权
当组件是另一个组件的子组件时,通常这两者都不会传入,在这容器就是父组件
注意应只使用renderTo或者applyTo其一,而不是两者同时使用

(5) 执行onRender
对Component的子类来说这很重要,所有DOM元素都在这一步插入
以渲染组件并将其绘制在屏幕上,在之后扩展Ext.Component或者任何子类的时候
每个子类原则上都应该首先调用它超类的onRender
以确保Ext.Component 基类可以插入渲染一个组件所需的核心DOM元素

(6) 配置显示模式
组件的元素根据hideMode属性来设置其显示模式
默认被设置为'display'(CSS display : none;)
但可以设置为'visibility'(CSS visibility:hidden;)和'offsets'
hideMode设置成'offsets'可以让组件的元素就位
并在X和Y坐标轴上负偏移1000像素

(7) 初始化overCls(如果配置过)
如果组件配置了overCls属性
则组件会指示其元素在它的mouseover事件上添加该CSS类
并在mouseout事件上设置removeOverCls属性

(8) 触发render事件
在这一步所有必需的元素都已经被插入DOM,并且都应用了样式
触发render事件,触发任何已注册的事件监听器

(9) 初始化组件的内容
如果组件配置了contentEl、html和/或tpl(Template)和data 属性的组合
则它会把相应的内容作为自己元素的子元素渲染
AbstractComponent 经过模型化设计
如果你愿意的话可以使用一个、两个或者全部(三个)属性
html将首先渲染,然后是contentEl,接着是tpl,最后是data

(10) 执行afterRender
afterRender是一个渲染后方法,由render方法自动调用
负责配置组件的尺寸,排列和定位组件,并往HTML内容添加样式
也负责初始化Resizable的一个实例(如果配置过)
把组件的元素设置为可滚动(如果配置过autoScroll配置项)
并使组件可拖动(如果做过相应配置)
最后,如果组件就兼容富网络应用(ARIA)做过配置,则部件也进行相应的初始化
注意:Component子类都应该要调用其超类的afterRender方法

(11) 触发afterrender事件
作用是让类知道所有关键渲染操作都已完毕,组件已经做好修改其元素的准备
为让你的子类可以执行DOM操作,这个事件通常是最佳监听对象

(12) 挂接afterRenderEvents
如果组件设置了一个afterRenderEvents配置对象
它将使用该配置对象把元素监听器挂接到可挂接的部件特有的元素引用
比如Component 的el和Panel的body

(13) 初始化组件的元素以获取焦点
被配置为可聚焦(focusAble)的组件和
有可聚焦元素的组件将绑定到内部的onFocus处理程序上
这个底层命令负责处理那些在管理了底层元素的focus和blur事件后
可以触发自身自定义focus和blue事件的组件

(14) 隐藏组件
如果组件的配置中hidden设为true,则执行元素的hide方法
可以通过配置的hideMode属性来隐藏该组件

(15) 禁用组件
如果组件的配置中disabled设为true,则执行组件的disable方法
可以有效地禁用该部件
注意:这里的禁用组件操作不会触发disable方法

销毁(Destruction)阶段

销毁一个组件要执行的任务
比如把自身和所有子组件从DOM树中移除,释放内存
并撤销组件在ComponentManager 类的注册,以及撤销事件监听器的注册
image
销毁阶段的各个步骤:
(1) 触发beforedestroy
这是一个可取消事件,以防组件在事件处理程序返回false的时候被销毁

(2) 调用beforeDestroy
这个方法是组件的destroy方法中最早调用的一个
也是移除任何非组件元素(比如工具栏或者按钮)的绝佳时机
Component的任何子类都应该调用其超类的beforeDestroy方法

(3) 撤销组件关于浮动的注册
如果一个组件是浮动的,它在FloatingManager的注册就被撤销

(4) 从父容器中移除组件
如果组件是一个父容器的子组件,它就从父容器被移除

(5) 调用onDestroy
onDestroy方法负责以下任务:
首先是立刻销毁任何配置过的拖放代理
然后是销毁Resizer(如果配置过)
如果注册过焦点DelayedTask,就把它从组件中移除
如果组件被配置为监控浏览器的调整尺寸事件,则移除该调整尺寸事件处理程序
如果组件配置了ComponentLayout、LoadMask和任何浮动子元素,则进行销毁

(6) 销毁注册的插件
循环访问所有注册过的插件,调用它们各自的destroy方法

(7) 清除元素和元素监听器
如果组件已经被渲染,则移除任何注册到其Element的处理程序
并将Element从DOM中移除

(8) 触发destroy事件
事件触发任何注册过的事件处理程序,标志着该组件不在存在于DOM中

(9) 撤销组件在ComponentManager的注册
移除ComponentManager类中对组件的引用

(10) 销毁状态混入类
调用状态混入类以进行销毁,撤销任何状态特有的组件事件的注册

(11) 清除组件的事件处理程序
撤销所有事件处理程序在组件的注册

组件与HTML(Components and HTML)

组件(Ext.Component)会生成HTML标签
编码时只需要定义组件,会自动生成HTML标签
定义不同的组件配置项时,会生成不同的HTML标签及其属性

比如定义一个最简单的组件

var simpleComponent = Ext.create('Ext.Component', {
    html : 'Ext JS Essentials!',
    renderTo: Ext.getBody()
});

将会自动生成HTML标签如下

<div class="x-component x-component-default x-border-box" id="component-1009">Ext JS Essentials!</div>

组件并不直接管理HTML标签,而是通过Ext.dom.Element类型去管理HTML DOM
可以通过组件的el属性去获得其生成的HTML DOM
注意:组件要在渲染完成后才会生成HTML DOM
如果需要操作DOM可以监听afterrender事件
注意:不建议直接操作组件的DOM,建议使用组件的API

Ext.create('Ext.Component', {
    html : 'Ext JS Essentials!',
    renderTo : Ext.getBody(),
    listeners: {
        afterrender: function(comp) {
            comp.el.setStyle('background-color', 'red');
        }
    }
});

组件的层次结构

容器(Ext.container.Container)是可以包含其他组件的组件(Ext.Component)
典型的应用程序由树状结构中的许多嵌套组件组成,这种结构称为组件层次结构
容器负责管理其子组件的组件生命周期,包括创建、呈现、调整大小和定位以及销毁
典型应用程序的组件层次结构从顶部的一个视区(Viewport)开始
视区中嵌套有其他容器、组件
image

添加子项到容器中

使用容器的items配置属性将子组件添加到容器中

实例:

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

xtype属性

说明

xtype定义过程:
组件类型都有定义xtype配置项
在组件的源代码中有alias:’widget.xtypeName’的定义
ExtJS类系统会将其注册到Ext.ComponetMananger中
例如Ext.panel.Panel的xtype是panel

xtype使用过程:
在UI组件实例化时使用xtype配置项
ExtJS初始化组件时,会读取其items属性,检查是否包含xtype配置项
如果有xtype配置项,则会使用ComponentManger.create方法创建其类型实例

使用xtype的好处

允许组件延迟实例化,加速复杂UI界面的实例化,提高加载速度
延迟加载(lazily instantiate)组件,组件在有必要时才进行渲染
减少代码输入,代码结构更加简洁
简化类型实例化过程

自定义xtype

//自定义组件并定义组件xtype
Ext.define('PandaApp.PandaComponet', {
    extend: 'Ext.panel.Panel',
    //定义xtype
    alias: 'widget.PandaComponet',
    html: 'PandaHtmlTestContent'
});

//使用测试组件xtype
Ext.create('Ext.panel.Panel', {
    renderTo: Ext.getBody(), 
    'items': [
        {
            xtype:'PandaComponet',
            colsable: true
        }
    ]
});

使用xtype

{
    xtype: 'panel',
    height: 200,
    width: 200,
    title: 'Panda Title',
    closable: true,
    draggable: true,
    renderTo: Ext.getBody(),
    items: [
        {
            xtype: 'button',
            text: 'Panda Button'
        }
    ]
}

实例2:

//自定义组件
Ext.define('PandaApp.TestComponent',{
    extend: 'Ext.Component',
    //定义组件别名
    alias: 'widget.testComponent',
    //定义类别名
    alternateClassName: 'testComponent',

    testMethod:function () {
        console.log('Panda666');
    },
});

//创建组件实例
let testComponent = Ext.create({
    //使用别名创建组件
    xtype: 'testComponent'
});

testComponent.testMethod();

常用组件的xtype

xtype Class
actionsheet Ext.ActionSheet
audio Ext.Audio
button Ext.Button
image Ext.Img
label Ext.Label
loadmask Ext.LoadMask
panel Ext.Panel
segmentedbutton Ext.SegmentedButton
sheet Ext.Sheet
spacer Ext.Spacer
titlebar Ext.TitleBar
toolbar Ext.Toolbar
video Ext.Video
carousel Ext.carousel.Carousel
navigationview Ext.navigation.View
datepicker Ext.picker.Date
picker Ext.picker.Picker
slider Ext.slider.Slider
thumb Ext.slider.Thumb
tabpanel Ext.tab.Panel
viewport Ext.viewport.Default

DataView Components
dataview Ext.dataview.DataView
list Ext.dataview.List
nestedlist Ext.dataview.NestedList

Form Components
checkboxfield Ext.field.Checkbox
datepickerfield Ext.field.DatePicker
emailfield Ext.field.Email
hiddenfield Ext.field.Hidden
numberfield Ext.field.Number
passwordfield Ext.field.Password
radiofield Ext.field.Radio
searchfield Ext.field.Search
selectfield Ext.field.Select
sliderfield Ext.field.Slider
spinnerfield Ext.field.Spinner
textfield Ext.field.Text
textareafield Ext.field.TextArea
togglefield Ext.field.Toggle
urlfield Ext.field.Url
fieldset Ext.form.FieldSet
formpanel Ext.form.Panel

组件渲染(Component rendering)

说明

Ext.Component支持 直接渲染 和 懒惰(按需)渲染 两种模式

直接渲染:在Component的子类内定义renderTo或者 applyTo配置项
按需渲染:调用Component的子类的render()方法

直接渲染

使用renderTo配置项

Ext.create('Ext.panel.Panel', {
    id: 'pandaId',
    width: 300,
    height: 300,
    title: 'Panda Title',
    closable: true,
    draggable: true,
    renderTo: document.body
});

按需渲染

调用render方法(引用形式)

var panel = Ext.create('Ext.panel.Panel', {
    id: 'pandaId',
    width: 300,
    height: 300,
    title: 'Panda Title',
    closable: true,
    draggable: true
});

panel.render(document.body);

调用render方法(ID选择符)

<div id="box">Panda</div>
var panel = Ext.create('Ext.panel.Panel', {
    id: 'pandaId',
    width: 300,
    height: 300,
    title: 'Panda Title',
    closable: true,
    draggable: true
});

panel.render('box');

延迟实例化

因为并非所有组件都需要立即实例化
根据应用程序的使用方式,某些组件可能不会实例化
例如,使用选项卡面板的应用程序只需要在用户单击每个选项卡时呈现每个选项卡的内容,并不需要每个选项卡都进行实例化
这就是xtype的优势,允许预先配置容器子级,但在容器必要时才进行实例化

实例:

{
    xtype: 'panel',
    height: 100,
    width: 200,
    items: [
        {
            xtype: 'panel', 
            title: 'Tab One', 
            html: 'The first tab', 
            listeners: { 
                render: function() { 
                    Ext.MessageBox.alert('Rendered One', 'Tab One was rendered.'); 
                }
            }
        },
        {
            xtype: 'panel', 
            title: 'Tab Two', 
            html: 'The second tab', 
            listeners: { 
                render: function() { 
                    Ext.MessageBox.alert('Rendered One', 'Tab Two was rendered.');
                }
            }
        }
    ]
}

显示和隐藏

所有组件都内置show()和hide()方法

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

panel.show();

用于隐藏组件的默认CSS方法是“display:none”
但可以使用hideMode配置项更改此行为

var panel = Ext.create('Ext.panel.Panel', {
    renderTo: Ext.getBody(),
    title: 'Test',
    html: 'Test Panel',
    hideMode: 'visibility' // use the CSS visibility property to show and hide this component
});

组件浮动

浮动组件使用CSS绝对定位在文档流外部进行,不参与其父容器布局
默认情况下,某些组件(如Windows)默认就是浮动的
可以使用float配置使组件浮动
通常,组件要么指定了renderTo配置,要么作为容器的子组件添加
但对于浮动组件,这两个配置项都不需要
浮动组件在第一次调用其show方法时自动呈现到文档(body)

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

使用xtype定义:

items: [
    {
        xtype: 'button',
        text: 'PandaButton',
        handler: function(){
            Ext.getCmp('panda-window').show();
        }
    },
    {
        xtype: 'window',
        id: 'panda-window',
        minWidth: 500,
        minHeight: 200,
        centerd: true,
        title: 'Panda Window',
        html: 'panda666.com'
    }
]

组件可拖拽

使用draggable配置项即可
注意:window默认开启拖拽功能

var panel = Ext.create('Ext.panel.Panel', {
    width: 200,
    height: 100,
    floating: true, // make this panel an absolutely-positioned floating component
    title: 'Test',
    draggable: true,
    html: 'Test Panel'
});
posted @ 2022-07-08 22:45  重庆熊猫  阅读(1362)  评论(0编辑  收藏  举报