1.Config Options 和Public Properties区别:
配置项是在创建组件时生成,相当于构造函数的参数;属性是在组件创建后能取到的组件属性,相当于成员变量
2.初始化执行过程
controller的init方法优先于application的launch方法执行,而Ext.onReady方法是在页面加载完DOM后执行,延迟加载(不需要加载图片 )
3.extjs的事件机制
Ext.util.Observable.js是extjs的自定义事件 和Ext.EventMangement.js解决浏览器对事件兼容问题,和对原始事件的封装
4.注意extjs事件中的两个重要属性参数(scope和single)
extjs利用on方法绑定事件时,参数scope默认是触发该事件的对象this,实际开发中,可以将这个scope复写为其他任意组件;single默认为false,比如渲染renderer这类事件,只需要渲染一次,可以将事件定义为只触发一次,节约内存资源。
myGridPanel.on('hide',this.handlerClick,this,{
single:true,
delay:100
})
on方法参数分别为eventName,fn,scope,options(scope:'',delay:'',single:'',buffer:'',target:'',element:'')
另外,Events中有些事件参数有Ext.EventObject,可以使用e.getTarget获得触发事件的组件
5.在创建自定义类时,先构造(constructor)后初始化(initComponent)。如:
Ext.define('Btn',{
extend:'Ext.button.Button',
initComponent:function(){
alert('后初始化部件启动...');
},
constructor:function(){
this.text = new Date();
this.renderTo = Ext.getBody();
this.callParent();
alert('先构造函数启动...');
}
});
Ext.onReady(function(){
Ext.create('Btn');
});
6-1.extjs的store中的proxy可以配置多个url(增删改)
proxy:{
type:'ajax',
api:{
read:'url1',
update:'url2'
create:'url3',
Destory:'url4'
}
reader:{
root:'',
url:'',
successProperty:'success'
}
}
6-2.更新数据记录
this.getStore().sync()
7.Ext.data.Model是Ext.data.Record的升级版
8.extjs滚动条问题
在grid的columns里面配置数据变量,配置autoScrll:true,scroll:true后不会出现滚动条,但是写死又可以,不知道什么情况
可以控制具体是x方向还是y方向有滚动条overflowX:'auto'或者overflowX:'auto'
9.FormPanel的提交\加载
注意:后台传过来的json格式,如{success:ture,data:{xx:xxx,……}},与grid不同
myFormPanel.getForm().submit({//提交
//clientValidation: true,
url: 'xxx.action',
params: {
newStatus: 'delivered'
},
success: function(form, action) {
Ext.Msg.alert('Success', action.result.msg);
},
failure: function(form, action) {
Ext.Msg.alert('Failure', action.result.msg);
},
})
myFormPanel.getForm().load({//加载
url: 'xxx.action',
params: {
consignmentRef: myConsignmentRef
},
failure: function(form, action) {
Ext.Msg.alert("Load failed", action.result.errorMessage);
}
});
10.gridPanel的提交、加载
注意:后台传过来的json格式,如{total:12,rows:[{xx:xxx,……},{}]},与form不同
myGridPanel.store.load({
params:{params:xx}
});
默认参数提交,即每次请求都会提交的参数
myGridPanel.store.proxy.extraParams={xxx:xx}
11.Ajax请求提交
Ext.Ajax.request({
url: 'xxx.action',
params: {
id: 1
},
success: function(response){
var text = response.responseText;
// Ext.JSON.decode(text)
}
});
12.disable与readOnly区别
有时候form表单中不想用户编辑。disable:true,视图变灰,而且提交没有此域;而readOnly可以提交
13.动态构建gridPanel
有时候需求为:gridPanel的列不固定,需要动态实现,则可以采用如下方法
创建一个空gridPanel,store:null,columns:[]
通过ajax请求获取columns,并构建相应的store
myGridPanel.reconfigure(store,columns)
14.Extjs选择器
根据id找组件:Ext.getCmp('id')
某组件上面的组件 MyCom.up('form');某组件下面的组件MyCom.down('form');
某组件的父和兄弟:MyCom.ownerCt;MyCom.nextSibling();MyCom.previousSibling();
15.grid的多选配置项
//checkbox放在最后一栏需要配置:injectCheckbox : Number/String
selModel : Ext.create('Ext.selection.CheckboxRowModel',{injectCheckbox : 'last'}),
multiSelect:'MULTI'
16.extjs触发事件函数
extjs4大型项目一般采用MVC模式,事件触发写在controller(详情见API中Ext.app.Controller),根据别名作为选择器如:
Ext.define('MyApp.controller.Users', {
extend: 'Ext.app.Controller',
models:[],
stores:[],
views:['myaliasname'],
init: function() {
this.control({
'myaliasname': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
console.log('The panel was rendered');
}
});
一些比较简单的事件,可以使用listeners属性完成 ,如:
listeners: {
click: {
element: 'el',
fn: function(){ console.log('click el'); }
},
dblclick: {
element: 'body',
fn: function(){ console.log('dblclick body'); }
}
}
或者handler属性,一般是按钮,combobox等组件,和listeners类似
17.extjs中config中配置对象的属性可以使用get方法获取
Ext.define('SmartPhone', {
config: {
hasTouchScreen: false,
operatingSystem: 'Other',
price: 500
},
isExpensive: false,
constructor: function(config) {
this.initConfig(config);
},
applyPrice: function(price) {
this.isExpensive = (price > 500);
return price;
},
applyOperatingSystem: function(operatingSystem) {
if (!(/^(iOS|Android|BlackBerry)$/i).test(operatingSystem)) {
return 'Other';
}
return operatingSystem;
}
});
var iPhone = new SmartPhone({
hasTouchScreen: true,
operatingSystem: 'iOS'
});
iPhone.getPrice(); // 500;
iPhone.getOperatingSystem(); // 'iOS'
iPhone.getHasTouchScreen(); // true;
iPhone.hasTouchScreen(); // true
iPhone.isExpensive; // false;
iPhone.setPrice(600);
iPhone.getPrice(); // 600
iPhone.isExpensive; // true;
iPhone.setOperatingSystem('AlienOS');
iPhone.getOperatingSystem(); // 'Other'
18.extjs对象中配置static中的方法为静态方法:
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');
18.extjs动态添加和删除容器内的组件
添加:
方法一:在父组件容器里面配置空items,即items:[],—>创建的子组件—>像操作数组一样push到父容器内,父容器.push(子容器)—>父容器重新渲染一次,父组件.doLayout()
方法二:创建的子组件—>调用父容器的add方法,父容器.add(子组件)
删除:
1.针对添加方法一的删除:
将items内的子组件删除:var destroyItem = 父容器.items.items.pop()—>destroyItem.destroy()
2.针对添加方法二的删除:
直接调用父容器的remove方法:父容器.remove(子组件),子组件内可以配置itemId则父容器.remove(‘itemId’)
19.extjs中json的处理
1.将json格式的字符串转换为json对象
Ext.JSON.decode(string)
JSON.parse(string)
eval("("+string+")");//注意eval里面有括号
2.将json对象转换为json格式的字符串
Ext.JSON.encode(json)
JSON.stringify(json)
20.extjs store加载后callback函数的使用
store.load({
scope: this,
callback: function(records, operation, success) {
// 数据加载后后继操作
console.log(records);
}
});
21.在调试extjs时,注意事项
注意console.log()和alert()的区别,console.log()显示的为打印的最终结果,类似异步执行;alert停在当前,后面的语句不会执行。如果需要等待(延迟渲染、ajax异步请求),可以使用setTimeout(function(){},1000),在function里面写好需要执行的语句
22.extjs组件释放,内存泄漏问题
组件创建后未销毁,一般这些组件继承Ext.Component,它在创建时会注册到Ext.ComponentMgr中(所以在检查组件销毁,可以执行Ext.ComponentMgr.getCount()或ComponentMgr.each(function(key,value,length){console.log(key)})查看组件),不调用destroy方法是不会从中移除的,所以它永远不会被释放。一般调用removeAll方法(abstractContainer子类,比如panel)可以实现级联销毁。也可以在initComponent,destroy事件中递归执行destroy()方法。对于组件销毁了查看store的销毁情况,Ext.data.StoreManager.getCount或each。默认store的配置autoDestroy为ture,extjs4后改为私有方法。默认组件销毁,store也跟着销毁了。如果store里面配置了storeId,store实例会在storeManager中保留,需要手动销毁!Ext.data.AbstractStore的源码:
destroyStore: function() {
var me = this;
if (!me.isDestroyed) {
if (me.storeId) {
Ext.data.StoreManager.unregister(me);
}
me.clearData();
me.data = me.tree = me.sorters = me.filters = me.groupers = null;
if (me.reader) {
me.reader.destroyReader();
}
me.proxy = me.reader = me.writer = null;
me.clearListeners();
me.isDestroyed = true;
if (me.implicitModel) {
Ext.destroy(me.model);
} else {
me.model = null;
}
}
}
23.采用事件冒泡机制,避免每个子组件绑定事件,提高性能
extjs的委托应该是事件冒泡的演变(不确定),一个委托模式的示例是工具条有10个按钮,而你希望在用户将鼠标移动到按钮上面时,为每个按钮委派一个Ext.Tooltip,而且每个Ext.Tooltip都显示不同的文本。如果你创建10个Ext.Tooltip并委派给10个按钮,那么它不是一个优化的解决方案。你只需要创建一个Ext.Tooltip并委派给10个按钮的父元素,也就是工具条。当用户将鼠标移动到工具条上方时,你可以显示相同的Ext.Tooltip,但其文本可根据目标元素(实际上就是按钮)而显示不同的文本(越多getTarget方法可了解如何获取目标元素)。使用这个技术,只需要创建1个Ext.Tooltip,而且只需要在工具条绑定一个监听事件。这可节省内存使用,而且在你的应用运行时实现了相同的效果。找到示例中Ext.Tooltip的delegate属性信息
24.xtype和new、Ext.create区别
new,Ext.create方法先将class加载到内存,渲染时直接使用。会引起两个方面的问题。1.在渲染时访问其他组件可能引起null,因为其他组件不一定已经渲染。2.new和create方式容易导致内存泄漏。xtype实现了组件懒初始化,xtype先标识是哪个class,渲染时才将class加载到内存。new引起的内存泄漏的例子:
如 tbar = [new TextField({...})],tbar所在的Grid作为TabItem,并且该TabItem延迟渲染,那么由于new TextField({...})已经注册,但因为未渲染,toolbar中未添加该Field为其Item,导致未销毁组件。(解决办法:通过复写onDestroy主动销毁,或是使用{xtype:""}延迟组件创建),总之,如果主动new ...的组件,那么注意销毁时,是否销毁了相应的组件
25.内存泄漏注意事项
1、减少组件的嵌套
2、尽可能延迟HTMLElement的创建
DOM操作(读/写)的开销一向是昂贵的,尤其在IE6,读取DOM总会引起回滚。因此,经验法则是:尽可能延迟HTMLElement的创建 。以下是实现方式:
●组件Lazy初始化,这在xtype里可实现。
●尝试在渲染后(afterrender)后再执行昂贵的操作。
●避免在组件的构造函数或initComponent方法中对其它组件进行不必要的实例化或渲染。
26.注意combo的change事件
在combo的change事件中获取兄弟节点引起找不到兄弟节点。以为combo在渲染之后值就已经改变了,则执行change事件。而此时兄弟节点不一定渲染完毕。解决办法:在change事件前面判断value是否为空,是则return。
27.动态改变树节点的文字
先获取需要改变的节点(如itemclick事件,treePanel.getSelectionModel().getSeslection()获取target),获取的节点应该是Ext.data.Store.ImplicitModel(继承自Ext.data.Record也就是Ext.data.model),使用set('text','修改后需要显示的文字')方法,但是此时数据是dirty的,需要再次调用Model的commit方法。
28.store去重
虽然在store的model中配置idProperty作为“主键”去重,但是类似在多个combobox引用同一个store的场景下会造成重复项问题。
var store = Ext.create('Ext.data.Store', {
listeners: { load: function (store,records,successful) {
vat me = store;
var k, repeat = [], state = {};
me.each(function (r) {
k = r.get('需要去重复的键名称');
if (state[k]) repeat.push(r);
else state[k] = true;
});
me.remove(repeat);
}
}
});
笔记:
未完待续。。。