1. alias String/String[]
类别名列表,命名方式为<namespace>.<name>
namespace 描述了别名的类型,一律为小写
name:允许通过别名实现延迟实例化,一般不应再包含.分割的空间
以下是框架预定义的一些命名空间及其用法:
- feature - Grid features
- plugin - Plugins
- store - Ext.data.Store
- widget - Components
Ext.define('MyApp.CoolPanel', {
extend: 'Ext.panel.Panel',
alias: ['widget.coolpanel'],
title: 'Yeah!'
});
// Using Ext.create
Ext.create('widget.coolpanel');
// Using the shorthand for defining widgets by xtype
Ext.widget('panel', {
items: [
{xtype: 'coolpanel', html: 'Foo'},
{xtype: 'coolpanel', html: 'Bar'}
]
});
2. alternateClassName : String / String[]
定义了类的可选类名,例如:
Ext.define('Developer', {
alternateClassName: ['Coder', 'Hacker'],
code: function(msg) {
alert('Typing... ' + msg);
}
});
var joe = Ext.create('Developer');
joe.code('stackoverflow');
var rms = Ext.create('Hacker');
rms.code('hack hack');
3. cachedConfig : Object
缓存配置,基本与config一样,不同之处在于它是在类初次实例化后被处理的,并缓存在类原型对象中,可以供之后实例化对象共享使用。同样会像config配置一样生成getter/setter访问器。
这在生成一些较重对象时比较有用,类本身会确保只处理一次。
带默认值的配置项列表。
注意:你在自定义类和单例时,要确保在构造器中调用了 Ext.Base#initConfig,除非你是在扩展Component组件。
否则生成的getter/setter访问器将无法被初始化。
如果未明确声明,每个配置项在类创建期间,会在类原型对象中生成getter/setter访问器。
示例会将Person类的name属性转换为一个配置项
Ext.define('My.sample.Person', {
config: {
name: 'Mr. Unknown',
age: 0,
gender: 'Male'
},
constructor: function(config) {
this.initConfig(config);
return this;
}
// ...
});
在该类中,this.name仍然会有一个默认值 "Mr. Unknown",通过getter/setter访问器,可以实现不牺牲封装性的情况下,进行公开访问。
var jacky = new Person({
name: "Jacky",
age: 35
});
alert(jacky.getAge()); // alerts 35
alert(jacky.getGender()); // alerts "Male"
jacky.walk(10); // alerts "Jacky is walking 10 steps"
jacky.setName("Mr. Nguyen");
alert(jacky.getName()); // alerts "Mr. Nguyen"
jacky.walk(10); // alerts "Mr. Nguyen is walking 10 steps"
这里可以注意到我们在构造器中调用了 this.initConfig ,并传入了一个config对象。这里发生了两个关键步骤:
- 当类被实例化时,传入的config对象将会与默认配置对象合并。
- 使用配置值调用对应的setter方法。
除了要存储值以外,setter方法在框架中还有两个责任:
- 在将值存储到实例时,过滤/验证/转换传入的值。
- 在值设定完成后或发生前后不一致的变动时,发出事件通知或进行后置处理。
遵循以下的标准约定,可以使用applyXXX和updateXXX这两个对应于setter的额外方法,可以实现在值被设置的前后添加一些自定义的业务逻辑。回到例子,让我们验证一下age是一个正数,并发出一个agechange通知信号:
Ext.define('My.sample.Person', {
config: {
// ...
},
constructor: {
// ...
},
applyAge: function(age) {
if (typeof age !== 'number' || age < 0) {
console.warn("Invalid age, must be a positive number");
return;
}
return age;
},
updateAge: function(newAge, oldAge) {
// age has changed from "oldAge" to "newAge"
this.fireEvent('agechange', this, newAge, oldAge);
}
// ...
});
var jacky = new Person({
name: "Jacky",
age: 'invalid'
});
alert(jacky.getAge()); // alerts 0
alert(jacky.setAge(-100)); // alerts 0
alert(jacky.getAge()); // alerts 0
alert(jacky.setAge(35)); // alerts 0
alert(jacky.getAge()); // alerts 35
也就是说,利用config配置你就无需明确定义getter/setter方法,并且在必要时,可以可以实现对应的applyXXX和updateXXX方法。这样做,确保了代码的一致性,符合最小知识原则。
当涉及到继承时,父类的配置会递归地与子类的配置合并,mixins混入配置也是如此。
5. eventedConfig : Object
事件化配置。如config一样生成对应的getter/setter方法,不同的是在值发生变动时会对应发出before{cfg}change 和{cfg}change通知。
注:在自定义类时,需要扩展Ext.Evented类,示例如下:
Ext.define('MyApp.util.Test', {
extend: 'Ext.Evented',
eventedConfig: {
foo: null
}
});
在该例子中,foo配置项初始值为null,现在调用setFoo方法改变foo取值将触发beforefoochange事件处理。在listeners配置的before事件处理器返回false时可以实现对setter方法的挂起。
var test = Ext.create('MyApp.util.Test', {
listeners: {
beforefoochange: function (instance, newValue, oldValue) {
return newValue !== 'bar';
},
foochange: function (instance, newValue, oldValue) {
console.log('foo changed to:', newValue);
}
}
});
test.setFoo('bar');
父类扩展,示例如下:
Ext.define('Person', {
say: function(text) { alert(text); }
});
Ext.define('Developer', {
extend: 'Person',
say: function(text) { this.callParent(["print "+text]); }
});
可继承静态方法配置。与statics类似,不同的地方在于配置的方法可以被子类继承。
混入,即将指定的类成员添加到当前类中,本质是通过改写的方式扩展类的成员定义,可以实现通用逻辑的复用。
示例如下:
Ext.define('CanSing', {
sing: function() {
alert("For he's a jolly good fellow...")
}
});
Ext.define('Musician', {
mixins: ['CanSing']
})
此时Musician类就拥有了一个sing方法。但是如果Musician已经有了一个同名的sing方法,那该如何处理?
可以通过明确访问mixins对象的指定汇入项的函数:
Ext.define('Musician', {
mixins: {
canSing: 'CanSing'
},
sing: function() {
// delegate singing operation to mixin
this.mixins.canSing.sing.call(this);
}
})
覆写。可以通过该配置改写target配置指定的类的定义。
私有配置。该配置用于定义只在框架类内部使用的方法列表。privates阻止了用户自定义逻辑对该配置项指定的方法的错误覆盖。
Ext.define('Computer', {
privates: {
runFactory: function(brand) {
// internal only processing of brand passed to factory
this.factory(brand);
}
},
factory: function (brand) {}
});
依赖类列表。在实例化类之前将先会加载依赖的类,例如:
Ext.define('Mother', {
requires: ['Child'],
giveBirth: function() {
// we can be sure that child class is available.
return new Child();
}
});
当设置为true时,该类将作为单例被实例化,示例如下:
Ext.define('Logger', {
singleton: true,
log: function(msg) {
console.log(msg);
}
});
Logger.log('Hello');
静态方法列表。示例如下:
Ext.define('Computer', {
statics: {
factory: function(brand) {
// 'this' in static methods refer to the class itself
return new this(brand);
}
},
constructor: function() { ... }
});
var dellComputer = Computer.factory('Dell');
可选依赖类。指定的类 不会确保一定会在当前类创建前被加载,但是可以保证Ext.onReady调用后可以被访问到,示例如下:
Ext.define('Mother', {
uses: ['Child'],
giveBirth: function() {
// This code might, or might not work:
// return new Child();
// Instead use Ext.create() to load the class at the spot if not loaded already:
return Ext.create('Child');
}
});
xtype是作为Component组件定义的缩写短名称存在的,优化组件的创建和渲染过程。
你可以指定一个widget.为前缀的别名配置项来自定义Component组件,示例如下:
Ext.define('PressMeButton', {
extend: 'Ext.button.Button',
alias: 'widget.pressmebutton',
text: 'Press Me'
});
任何一个组件都可以通过一个带xtype的配置对象来创建。这样无需事先将实例化好的组件作为参数传给要定义的组件,避免了不必要的实例化造成的资源浪费。复杂情况下,可以显著提升组件的渲染效率。
// Explicit creation of contained Components:
var panel = new Ext.Panel({
// ...
items: [
Ext.create('Ext.button.Button', {
text: 'OK'
})
]
});
// Implicit creation using xtype:
var panel = new Ext.Panel({
// ...
items: [{
xtype: 'button',
text: 'OK'
}]
});