解读Ext.util.MixedCollection(一)之基本操作
2012-02-05 15:53 尔 阅读(358) 评论(0) 收藏 举报感觉痛苦期过去了那么一点,现在,借助google,犀牛书,红宝书,跟着作者的思路,看他们有目的封装,层层递进,到最后搭建出EXT的框架,自己有一种说不出的兴奋感
Ext.util.MixedCollection---Ext一个比较霸道的自定义的数据结构,是构建Store的基础,Store又是Ext的数据处理层,又是搭建上层UI的支撑。
我自己是把Ext.util.MixedCollection看做一个map和数组的合体的,实现的方法也比较简单,就是在map和数组各存一份数据
Ext.util.MixedCollection = function(allowFunctions, keyFn){
//存放value的一个数组
this.items = [];
//维护key—value,这样查找效率会很高
this.map = {};
//存放key的数组
this.keys = [];
//长度,所以可以把它可以当成 类数组
this.length = 0;
//添加了五个事件,这也是原生集合所不能办到的
this.addEvents(
"clear",
"add",
"replace",
"remove",
"sort"
);
his.allowFunctions = allowFunctions === true;
//如何得到key值
if(keyFn){
this.getKey = keyFn;
}
//调用父类的构造函数
Ext.util.MixedCollection.superclass.constructor.call(this);
};
Ext.util.MixedCollection实现了Ext.util.Observabl接口,所以它可以支持“事件”了,并且给它的原型对象上添加了一些方法和属性
Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {.......},
//添加方法
add: function(key, o){
//如果参数长度为一
//value为传入的参数,key为value的id
if(arguments.length == 1){
o = arguments[0];
key = this.getKey(o);
}
if(typeof key != 'undefined' && key !== null){
var old = this.map[key];
if(typeof old != 'undefined'){
return this.replace(key, o);
}
this.map[key] = o;
}
//下面是更新这个数据结构
//长度+1
this.length++;
//value推入items
this.items.push(o);
//key推入keys
this.keys.push(key);
//并且触发add事件,add绑定的函数会响应
this.fireEvent('add', this.length-1, o, key);
//返回value
return o;
},
//替换
replace : function(key, o){
//同add
if(arguments.length == 1){
o = arguments[0];
key = this.getKey(o);
}
var old = this.map[key];
//如果没有此key
if(typeof key == "undefined" || key === null || typeof old == "undefined"){
//做添加处理
return this.add(key, o);
}
//查找key的位置
var index = this.indexOfKey(key);
//更新items
this.items[index] = o;
//更新map
this.map[key] = o;
//触发replace事件
this.fireEvent("replace", key, old, o);
return o;
},
//比较简单可以传一个参数或者对象
addAll : function(objs){
//传的是多个参数或者是一个数组
if(arguments.length > 1 || Ext.isArray(objs)){
var args = arguments.length > 1 ? arguments : objs;
for(var i = 0, len = args.length; i < len; i++){
//add处理
this.add(args[i]);
}
}else{
for(var key in objs){
//这个集合里的元素允许添加函数对象或者
if(this.allowFunctions || typeof objs[key] != "function"){
this.add(key, objs[key]);
}
}
}
},
//迭代,有一个安全问题
//如果迭代过程,对此集合remove操作,会出现问题
//所以先创建一个items的副本
each : function(fn, scope){
//创建items副本
//迭代的是这个副本
var items = [].concat(this.items);
for(var i = 0, len = items.length; i < len; i++){
//如果传入的fn参数返回false立即退出迭代
//这样就不用遍历所有元素
//只要找到需要的那个元素,就立即返回false,节省效率
if(fn.call(scope || items[i], items[i], i, len) === false){
break;
}
}
},
//比较奇怪的是没做迭代保护
eachKey : function(fn, scope){
for(var i = 0, len = this.keys.length; i < len; i++){
fn.call(scope || window, this.keys[i], this.items[i], i, len);
}
},
//很简单,传入的fn参数返回true变算找到
find : function(fn, scope){
for(var i = 0, len = this.items.length; i < len; i++){
if(fn.call(scope || window, this.items[i], this.keys[i])){
return this.items[i];
}
}
return null;
},
//插入操作
insert : function(index, key, o){
//如果只传入2个参数,做参数移位
if(arguments.length == 2){
//o指向传入的key位置的参数
o = arguments[1];
//key通过getKey来获得,也就是o的id
key = this.getKey(o);
}
//为什么要挂起事件?
//网上查不到任何资料,水平问题理解可能并不正确
//我个人的理解是,当做insert操作时,当key已经存在时,
//ext做的是先删除 ,再添加
//如果不挂起事件,就会感知到触发的remove事件
//然后在add的时候触发add事件
//显然逻辑上插入的时候应该是只有add事件,而没有remove事件
//所以再删除之前先挂起,删除后再恢复以便能感知add事件。
if(this.containsKey(key)){
//挂起事件
this.suspendEvents();
//个人感觉叫removerByKey比较好
//删除对应key-value对
this.removeKey(key);
//恢复事件
this.resumeEvents();
}
if(index >= this.length){
return this.add(key, o);
}
this.length++;
this.items.splice(index, 0, o);
if(typeof key != "undefined" && key !== null){
this.map[key] = o;
}
this.keys.splice(index, 0, key);
this.fireEvent("add", index, o, key);
return o;
},
//重置
clear : function(){
this.length = 0;
this.items = [];
this.keys = [];
this.map = {};
this.fireEvent("clear");
},
//没什么说的,很简单,返回一个索引从start到end的Array(items)
getRange : function(start, end){
var items = this.items;
if(items.length < 1){
return [];
}
//容错处理
start = start || 0;
//容错处理,没第二个属性,就到最后一个
end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
var i, r = [];
if(start <= end){
for(i = start; i <= end; i++) {
r[r.length] = items[i];
}
}else{
for(i = start; i >= end; i--) {
r[r.length] = items[i];
}
}
return r;
},
浙公网安备 33010602011771号