Alternate names
Ext.layout.CardLayoutHierarchy
Ext.BaseExt.layout.LayoutExt.layout.container.ContainerExt.layout.container.FitExt.layout.container.CardInherited mixins
Files
此布局管理多个子组件, 每个都完全填满父容器, 而每次仅显示一个. 此布局样式多用于向导, 实现标签页布局等等. 此类应该通过`layout:'card' Ext.container.Container.layout属性来扩展和创建, 通常不需要直接通过类名关键字来创建.
CardLayout的核心方法是setActiveItem. 因为一次只能够显示一个面板, 从一个组件切换到另一个的唯一方式就是 调用setActiveItem传入目标面板(或ID或索引). 布局本身并不提供任何用户交互界面来处理这种切换, 必须由开发人员来实现.
通过调用布局的setActiveItem方法, 来实现切换容器中当前显示的面板:
Ext.create('Ext.panel.Panel', {
layout: 'card',
items: [
{ html: 'Card 1' },
{ html: 'Card 2' }
],
renderTo: Ext.getBody()
});
p.getLayout().setActiveItem(1);
下面的例子演示了一个最简单的向导式界面的例子. 将一个按钮工具条添加到容器的底部, 来提供导航按钮. 这些按钮将统一由一个公共的 导航程序来处理. 注意: 针对CardLayout不同的用例(例如标签页控制)需要使用完全不同的实现方式. 而对于一些重量级的实现, 更换的 方法是通过继承和扩展CardLayout来提供自定义功能特性.
var navigate = function(panel, direction){
// 此程序可以包含一些控制导航步骤的必要业务逻辑. 比如调用setActiveItem, 管理导航按钮的状态,
// 处理可能出现的分支逻辑, 处理特殊操作像取消或结束等等. 一个完整的向导页, 对于复杂的需求
// 实现起来可能也会相当复杂, 在实际的程序中通常应该以继承CardLayout的方式来实现.
var layout = panel.getLayout();
layout[direction]();
Ext.getCmp('move-prev').setDisabled(!layout.getPrev());
Ext.getCmp('move-next').setDisabled(!layout.getNext());
};
Ext.create('Ext.panel.Panel', {
title: 'Example Wizard',
width: 300,
height: 200,
layout: 'card',
bodyStyle: 'padding:15px',
defaults: {
// 应用到所有子面板
border: false
},
// 这里仅仅用几个按钮来示例一种可能的导航场景.
bbar: [
{
id: 'move-prev',
text: 'Back',
handler: function(btn) {
navigate(btn.up("panel"), "prev");
},
disabled: true
},
'->', // 一个长间隔, 使两个按钮分布在两边
{
id: 'move-next',
text: 'Next',
handler: function(btn) {
navigate(btn.up("panel"), "next");
}
}
],
// 布局下的各子面板
items: [{
id: 'card-0',
html: '<h1>Welcome to the Wizard!</h1><p>Step 1 of 3</p>'
},{
id: 'card-1',
html: '<p>Step 2 of 3</p>'
},{
id: 'card-2',
html: '<h1>Congratulations!</h1><p>Step 3 of 3 - Complete</p>'
}],
renderTo: Ext.getBody()
});
如果容器包含的子项组件没有指定margin(边距)属性或通过CSS配置margin值, 那么这个默认margin属性将被应用到子项中.
此属性可以是个含边距值的对象, 格式如下:
{
top: (top margin),
right: (right margin),
bottom: (bottom margin),
left: (left margin)
}
此属性可以用一组空格分隔的数值所组成的字符串定义. 各值与边框的关联顺序的规则与CSS处理margin的规则相同:
Defaults to: {top: 0, right: 0, bottom: 0, left: 0}
'true'表示所有子项仅在被激活时才进行渲染, 'false'则表示所有子项与布局一起渲染(默认'false'). 如果在非默认显示的页面中 有大量的内容或重量级控件时, 将此配置设为'true'也许能够提高性能.
Defaults to: false
一个可选的添加到容器上的CSS class扩展类名. 此属性用于为容器或所有子组件添加基于CSS规则的自定义样式. 也可参考Ext.Component.componentCls
允许一下有效值:
Defaults to: 0
设此值为true
时, 无论垂直滚动条是否需要出现, 都会在页面为垂直滚动条预留出空间(如果该操作系统下的滚动条需要占用空间).
在某些系统实例中, 容器内容的高度会随着系统的操作发生变化, 而此时你又不希望所有子组件的宽度因滚动条的出现和消失而来回改变, 这种情况下此属性会变得很有用. 滚动条将会在预留的空间出现, 子组件的宽度也不会发生改变.
Ext.define('Employee', {
extend: 'Ext.data.Model',
fields: [
{name: 'rating', type: 'int'},
{name: 'salary', type: 'float'},
{name: 'name'}
]
});
function createFakeData(count) {
var firstNames = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay', 'Nicolas', 'Nige'],
lastNames = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson', 'Ferrero', 'White'],
ratings = [1, 2, 3, 4, 5],
salaries = [100, 400, 900, 1500, 1000000];
var data = [];
for (var i = 0; i < (count || 25); i++) {
var ratingId = Math.floor(Math.random() * ratings.length),
salaryId = Math.floor(Math.random() * salaries.length),
firstNameId = Math.floor(Math.random() * firstNames.length),
lastNameId = Math.floor(Math.random() * lastNames.length),
rating = ratings[ratingId],
salary = salaries[salaryId],
name = Ext.String.format("{0} {1}", firstNames[firstNameId], lastNames[lastNameId]);
data.push({
rating: rating,
salary: salary,
name: name
});
}
store.loadData(data);
}
// create the Data Store
var store = Ext.create('Ext.data.Store', {
id: 'store',
model: 'Employee',
proxy: {
type: 'memory'
}
});
createFakeData(10);
var grid = Ext.create('Ext.grid.Panel', {
title: 'Grid loaded with varying number of records',
anchor: '100%',
store: store,
columns: [{
xtype: 'rownumberer',
width: 40,
sortable: false
},{
text: 'Name',
flex: 1,
sortable: true,
dataIndex: 'name'
},{
text: 'Rating',
width: 125,
sortable: true,
dataIndex: 'rating'
},{
text: 'Salary',
width: 125,
sortable: true,
dataIndex: 'salary',
align: 'right',
renderer: Ext.util.Format.usMoney
}]
});
Ext.create('Ext.panel.Panel', {
renderTo: document.body,
width: 800,
height: 600,
layout: {
type: 'anchor',
reserveScrollbar: true // There will be a gap even when there's no scrollbar
},
autoScroll: true,
items: grid,
tbar: {
defaults: {
handler: function(b) {
createFakeData(b.count);
}
},
items: [{
text: '10 Items',
count: 10
},{
text: '100 Items',
count: 100
},{
text: '300 Items',
count: 300
},{
text: '1000 Items',
count: 1000
},{
text: '5000 Items',
count: 5000
}]
}
});
Defaults to: false
扩展事件
Defaults to: []
一个包含几个boolean值属性的对象, 包含的属性为指定子组件的ContextItem对哪些属性更新时需要动画效果. 例如, 一个Accordion布局应有:
{
y: true,
height: true
}
Defaults to: null
返回状态标记来描述如何处理跨浏览器的滚动条高度/宽度. 特别是IE在处理含'padding-bottom'的滚动条元素 时会出现问题(滚动条高度中会不含此padding值). 同样, 滚动条元素的子元素的'margin-bottom'属性值 可能会被丢失.
所有浏览器好像都会忽略子元素的'margin-right'属性和父元素的'padding-right'属性(当发生溢出时).
此方法返回一个二进制数值, 数值的各位根据不参与滚动条高度/宽度计算的因素进行设值:
为了解决'margin-bottom'属性的问题, 在子元素的最后创建一个0px高的元素就能够'隐藏'边界空白. 也可以通过将子元素再封装在一个元素中, 这样也能够'隐藏'边界空白. 封装元素的方式大概是 能够保持子元素右边界空白的唯一方案. 在Column布局中使用的就是这个方案.
为了解决'padding-bottom'属性的问题, 因为此样式来自父元素, 大概唯一简单的解决方法就是在子元素 的最后创建一个高度与'padding-bottom'值相等的元素. 而为了保护右padding, 新元素的宽度需要包含 右padding值.
发生溢出时, 用来修正body的padding值的元素.
发生溢出时, 用来修正body的padding值的元素.
本身
获取当前类的引用,此对象被实例化。不同于 statics,
this.self
是依赖范围,它意味着要使用动态继承。
参见 statics 详细对比
Ext.define('My.Cat', {
statics: {
speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
},
constructor: function() {
alert(this.self.speciesName); // 依赖 'this'
},
clone: function() {
return new this.self();
}
});
Ext.define('My.SnowLeopard', {
extend: 'My.Cat',
statics: {
speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'
}
});
var cat = new My.Cat(); // alerts 'Cat' 猫
var snowLeopard = new My.SnowLeopard(); // alerts 'Snow Leopard' 雪豹
var clone = snowLeopard.clone();
alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'
此方法添加解析到的每个参数到 childEls 数组.
成员
由所属Panel在开始处理折叠前调用. 大多数布局不需要覆盖此方法的默认Ext.emptyFn实现.
由所属Panel在开始处理展开前调用. 大多数布局不需要覆盖此方法的默认Ext.emptyFn实现.
除了基类的工作任务外, 容器还需要一些额外的缓存数据, 以下属性会被添加到所属上下文环境(ownerContext)中
Overrides: Ext.layout.Layout.beginLayout
在所有计算循环开始前重置DOM属性值, 对计算进行预处理.
覆盖时注意: 此函数处于DOM写阶段, 须避免任何对DOM的读操作.
此布局所属组件的上下文环境项.
执行当前布局的计算. 此函数至少会被调用一次, 如果属性done在返回前被标记为未完成状态,则将 重复调用此函数. 在刚进入此函数时done的属性值总是为'true'.
覆盖时注意: 此函数处于DOM读阶段, 须避免任何对DOM的写操作. 作为代替, DOM的写操作应该被写入 Ext.layout.ContextItem中以在下次刷新时更新DOM.
此布局所属组件的上下文环境项.
为容器进行溢出处理. 此方法应在布局计算出contentWidth/Height后立刻调用. 此方法需要的参数除了 传给calculate方法的ownerContext以外, 还需要容器尺寸大小(由getContainerSize返回的对象).
用一个二进制来标记溢出管理的尺寸. 0位代表'width', 1位代表'height'. 也就是, 当值为1是表示仅含'width', 值为2时表示仅含'height', 3表示二者皆有
调用原来的方法,这是以前的override重写
Ext.define('My.Cat', {
constructor: function() {
alert("I'm a cat!");
}
});
My.Cat.override({
constructor: function() {
alert("I'm going to be a cat!");
this.callOverridden();
alert("Meeeeoooowwww");
}
});
var kitty = new My.Cat(); // alerts "I'm going to be a cat!"
// alerts "I'm a cat!"
// alerts "Meeeeoooowwww"
This method has been deprecated since 4.1
版本 使用 callParent 代替.
参数的参数,数组或'参数'对象
来自当前方法,例如: this.callOverridden(arguments)
返回调用重写方法的结果。
所谓的"parent"方法是指当前的方法。 这是以前的方法派生或重写(参见 Ext.define)。
Ext.define('My.Base', {
constructor: function (x) {
this.x = x;
},
statics: {
method: function (x) {
return x;
}
}
});
Ext.define('My.Derived', {
extend: 'My.Base',
constructor: function () {
this.callParent([21]);
}
});
var obj = new My.Derived();
alert(obj.x); // alerts 21
这可以用来重写如下:
Ext.define('My.DerivedOverride', {
override: 'My.Derived',
constructor: function (x) {
this.callParent([x*2]); // 调用原来的My.Derived构造
}
});
var obj = new My.Derived();
alert(obj.x); // 现在提示 42
This also works with static methods.
Ext.define('My.Derived2', {
extend: 'My.Base',
statics: {
method: function (x) {
return this.callParent([x*2]); // 调用 My.Base.method
}
}
});
alert(My.Base.method(10); // alerts 10
alert(My.Derived2.method(10); // alerts 20
然后,它也可以重写静态方法。
Ext.define('My.Derived2Override', {
override: 'My.Derived2',
statics: {
method: function (x) {
return this.callParent([x*2]); // 调用 My.Derived2.method
}
}
});
alert(My.Derived2.method(10); // 现在提示 40
这个参数, 通过当前方法得到数组或者 arguments
对象,
例如: this.callParent(arguments)
返回调用父类的方法的结果。
此函数(如果被实现)会在布局即将完成循环周期(done没有被设为'false')时被调用. 一个布局 有可能在计算完成后而循环结束前就已经被清除, 这种情况下, 此函数将不被调用. 布局也可能在此函数调用 之后被执行清除, 这将导致calculate计算函数被重新执行, 然后再次调用此函数.
覆盖时注意: 此函数处于DOM读阶段, 须避免任何对DOM的写操作. 作为代替, DOM的写操作应该被写入 Ext.layout.ContextItem中以在下次刷新时更新DOM.
子类不一定要实现此函数, 事实上, 应仅在必要时才实现.
此布局所属组件的上下文环境项.
销毁此布局. 函数会从目标元素(target)中删除一个目标样式(targetCls)并调用'onDestroy'.
子类可以覆盖此函数或'onDestroy', 但是所有实现必须调用基类函数, 使基类能够完成清除工作.
此函数(或'onDestroy')可以由子类覆盖, 以用来清除事件处理或清除未直接管理的DOM节点.
创建一个元素, 以使下/右的'body padding'与浏览器保持一致. 此元素的尺寸定义是基于calculateOverflow的计算是否需要滚动条. 如果manageOverflow参数为'false', 那么此元素将不会被创建.
详情参见getScrollRangeFlags.
此函数(如果被实现)会在所有布局计算结束后调用. 很多方面与completeLayout类似. 此函数 可以对当前(或其他)布局变进行清除(参见Ext.layout.Context.invalidate), 但是最好避免这种 情况. 此函数应用来进行最后的读取操作, 所以最好不要在这个阶段进行任何清除布局操作. 不过此函数仍可以 用来执行最后的检查操作, 即使这些检查可能需要所有其他的布局都完成计算并清除某些计算结果.
覆盖时注意: 此函数处于DOM读阶段, 须避免任何对DOM的写操作. 作为代替, DOM的写操作应该被写入 Ext.layout.ContextItem中以在下次刷新时更新DOM.
子类不一定要实现此函数, 事实上, 应仅在必要时才实现.
此布局所属组件的上下文环境项.
此函数在所有布局都完成计算且计算结构都刷新到DOM时调用. 不会再有更多的布局被执行, 且此函数在每个 布局的执行过程中仅被调用一次. 基类组件布局会缓存lastComponentSize.
覆盖时注意: 此函数处于DOM写入阶段, 须避免任何对DOM的读操作.
子类不一定要实现此函数, 事实上, 应仅在必要时才实现.
此布局所属组件的上下文环境项.
返回容器的尺寸大小. 只有确定值的尺寸能够返回, 因为受外容器宽/高约束的包装模型的尺寸是由容器的布局决定的.
如果calculateOverflow方法已被调用且manageOverflow参数为'true', 那么尺寸可能需要根据滚动条的尺寸进行调整.
布局所属组件的上下文环境.
'true'表示容器的尺寸必须与DOM属性值一致.
Defaults to: false
返回一个子组件的数组. 或用于渲染阶段(布局基类的beforeLayout方法), 或用于布局阶段(onLayout方法).
of child components
Overrides: Ext.layout.Layout.getLayoutItems
这个类的初始化配置。典型例子:
Ext.define('My.awesome.Class', {
// 这是默认配置
config: {
name: 'Awesome',
isAwesome: true
},
constructor: function(config) {
this.initConfig(config);
}
});
var awesome = new My.awesome.Class({
name: 'Super Awesome'
});
alert(awesome.getName()); // 'Super Awesome' 超级棒
配置
mixins 混入原型 键-值对
在渲染前仅执行一次的初始化函数.
在所有布局上下文环境中的布局刷新都完成以后, 为每个布局进行调用.
Overrides: Ext.layout.Layout.notifyOwner
当组件内容的子项发送某种变化时, 调用此函数. 此函数默认调用布局所属组件的 Ext.AbstractComponent.updateLayout函数.
被改变的子组件.
返回'true'表示布局已对内容的变化进行处理.
Removes items in the childEls array based on the return value of a supplied test function. The function is called with a entry in childEls and if the test function return true, that entry is removed. If false, that entry is kept.
The test function.
将组件渲染到目标元素(Element)上
待渲染组件
模板元素
组件被渲染插入到模板元素中的位置
激活指定的面板.
var card1 = Ext.create('Ext.panel.Panel', {itemId: 'card-1'});
var card2 = Ext.create('Ext.panel.Panel', {itemId: 'card-2'});
var panel = Ext.create('Ext.panel.Panel', {
layout: 'card',
activeItem: 0,
items: [card1, card2]
});
// 以下写法等效:
panel.getLayout().setActiveItem(card2);
panel.getLayout().setActiveItem('card-2');
panel.getLayout().setActiveItem(1);
被激活的组件, 或返回'false'当无面板被激活时. 当传入的面板已经是当前激活时面板也将返回'false'.
获取从该对象被实例化的类的引用。 请注意不同于 self,
this.statics()
是独立的作用域,无论this
是否运行,总是返回其中的调用类。
Ext.define('My.Cat', {
statics: {
totalCreated: 0,
speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
},
constructor: function() {
var statics = this.statics();
alert(statics.speciesName); // 总是等于'Cat',无论'this'是什么,
// 相当于:My.Cat.speciesName
alert(this.self.speciesName); // 依赖 'this'
statics.totalCreated++;
},
clone: function() {
var cloned = new this.self; // 依赖 'this'
cloned.groupName = this.statics().speciesName; // 相当于: My.Cat.speciesName
return cloned;
}
});
Ext.define('My.SnowLeopard', {
extend: 'My.Cat',
statics: {
speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'
},
constructor: function() {
this.callParent();
}
});
var cat = new My.Cat(); // alerts 'Cat', 然后提示 'Cat'
var snowLeopard = new My.SnowLeopard(); // alerts 'Cat', 然后提示 'Snow Leopard'
var clone = snowLeopard.clone();
alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'
alert(clone.groupName); // alerts 'Cat'
alert(My.Cat.totalCreated); // alerts 3
配置扩展
方法/属性添加到这个类的原型。
Ext.define('My.awesome.Cat', {
constructor: function() {
...
}
});
My.awesome.Cat.implement({
meow: function() {
alert('Meowww...');
}
});
var kitty = new My.awesome.Cat;
kitty.meow();
成员
添加/重写这个类的静态属性。
Ext.define('My.cool.Class', {
...
});
My.cool.Class.addStatics({
someProperty: 'someValue', // My.cool.Class.someProperty = 'someValue'
method1: function() { ... }, // My.cool.Class.method1 = function() { ... };
method2: function() { ... } // My.cool.Class.method2 = function() { ... };
});
成员
this
这个类的原型借用另一个类的成员
Ext.define('Bank', {
money: '$$$',
printMoney: function() {
alert('$$$$$$$');
}
});
Ext.define('Thief', {
...
});
Thief.borrow(Bank, ['money', 'printMoney']);
var steve = new Thief();
alert(steve.money); // alerts '$$$'
steve.printMoney(); // alerts '$$$$$$$'
this 借用成员
创建这个类的新实例。
Ext.define('My.cool.Class', {
...
});
My.cool.Class.create({
someConfig: true
});
所有参数传递至类的构造。
创建的实例。
创建现有的原型方法的别名。例如:
Ext.define('My.cool.Class', {
method1: function() { ... },
method2: function() { ... }
});
var test = new My.cool.Class();
My.cool.Class.createAlias({
method3: 'method1',
method4: 'method2'
});
test.method3(); // test.method1()
My.cool.Class.createAlias('method5', 'method3');
test.method5(); // test.method3() -> test.method1()
别名新方法的名称,或对象设置多个别名。 参见flexSetter
原来的方法名
以字符串格式,获取当前类的名称。
Ext.define('My.cool.Class', {
constructor: function() {
alert(this.self.getName()); // alerts 'My.cool.Class'
}
});
My.cool.Class.getName(); // 'My.cool.Class'
className 类名
重写这个类的成员。通过callParent重写的方法可以调用。
Ext.define('My.Cat', {
constructor: function() {
alert("I'm a cat!");
}
});
My.Cat.override({
constructor: function() {
alert("I'm going to be a cat!");
this.callParent(arguments);
alert("Meeeeoooowwww");
}
});
var kitty = new My.Cat(); // alerts "I'm going to be a cat!我要成为一只猫!"
// alerts "I'm a cat!我是一只猫!"
// alerts "Meeeeoooowwww"
在4.1版本, 直接利用这种方法已经过时了。 使用 Ext.define 代替:
Ext.define('My.CatOverride', {
override: 'My.Cat',
constructor: function() {
alert("I'm going to be a cat!");
this.callParent(arguments);
alert("Meeeeoooowwww");
}
});
以上完成了相同的结果,但可以由Ext.Loader重写, 其目标类和生成过程中,可以决定是否需要根据目标类所需的状态覆盖管理(My.Cat)。
This method has been deprecated since 4.1.0
使用 Ext.define 代替
添加到这个类的属性。 这应当被指定为一个对象包含一个或多个属性的文字。
this class 当前类