解读Ext.util.MixedCollection(一)之基本操作

感觉痛苦期过去了那么一点,现在,借助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;

    },


你可能感兴趣的:(数据结构,function,Google,ext,null,insert)