javascript代码实例教程-jQuery.access源码分析

发布时间:2019-01-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-jQuery.access源码分析脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 基本理解

jQuery.attr是jquery.attr,jQuery.PRop,jQuery.css提供底层支持,jQuery里一个比较有特色的地方就是函数的重载, 比如attr,有如下几种重载

 

$('#box').attr('tITle')

$('#box').attr('title','标题')

$('#box').attr({title:'标题',data-menu-toggle:'dropdown'})

$('#box').attr('title',function () {....})

但是纵观jQuery.attr代码中,却没有判断value是不是存在啊之类的,ok,你猜对了,在access里实现了

 

复制代码

jQuery.fn.extend({

    attr: function (name, value) {

        return jQuery.access(this, jQuery.attr, name, value, arguments.length > 1);

    },

 

    removeAttr: function (name) {

        return this.each(function () {

            jQuery.removeAttr(this, name);

        });

    },

 

    prop: function (name, value) {

        return jQuery.access(this, jQuery.prop, name, value, arguments.length > 1);

    }

});

复制代码

 

 

源码分析

大致思路

 

1.首先判断key值是不是一个object,如果是,遍历key,递归调用jQuery.access,并将是否可以链式调用的标志位设置为true

2.判断value值是否已经定义,如果已经定义,说明是个set操作

2.1 set操作的是可链式调用的

2.2 如果value不是function,设置raw为true

2.3 判断key值是否为null或者undefined,key若为空值

2.3.1 如果value不是个函数,或者强制赋值raw为true,那么调用fn,可能是以下调用:$('#box').attr(null,{abc:'def',a:'1'})

2.3.1 如果value是个函数,将fn包装之,改变原来fn的作用域和参数

2.4 如果fn存在,遍历jQuery内部元素,分别执行set操作

3.首先判断是否为set方法,如果是,返回 elems,如果不是执行get操作(如果jQuery内部length为0,返回指定的默认空值)

复制代码

    // Multifunctional method to get and set values of a collection

    // The value/s can optionally be executed if it's a function

    /**

    attr: function (name, value) {

        return jQuery.access(this, jQuery.attr, name, value, arguments.length > 1);

    },

     *

     * @param elems jQuery的this

     * @param fn 函数

     * @param key 属性

     * @param value 值

     * @param chainable 是否可以链式调用,如果是get动作,为false,如果是set动作,为true

     * @param emptyGet 如果jQuery没有选中到元素的返回值

     * @param raw value是否为原始数据,如果raw是true,说明value是原始数据,如果是false,说明raw是个函数

     * @returns {*}

     */

    access: function( elems, fn, key, value, chainable, emptyGet, raw ) {

        VAR i = 0,

            length = elems.length,

            bulk = key == null; // bulk 体积,容量;大多数,大部分;大块

 

        // Sets many values

        /**

         * 如果参数key是对象,表示要设置多个属性,则遍历参数key,遍历调用access方法

         *

         * $('#box').attr({data:1,def:'addd'});

         */

        if ( jQuery.tyPE( key ) === "object" ) {

            chainable = true; //表示可以链式调用

            for ( i in key ) {

                jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );

            }

 

        // Sets one value

 

            /**

             * $('#box').attr('customvalue','abc')

             * $('#box').attr('customvalue',function (value) {});

             */

 

        } else if ( value !== undefined ) {

            chainable = true;

 

            if ( !jQuery.isFunction( value ) ) {

                raw = true;

            }

 

            if ( bulk ) { // if (key == null && value !== undefined)

                // Bulk operations run against the entire set

                /**

                 * $('#box').attr(undefined,'abc')

                 *

                 * jQuery.attr.call(elems,value); 调用完毕之后,将fn设置为空

                 */

                if ( raw ) {

                    fn.call( elems, value );

                    fn = null;

 

                // ...except when executing function values

                    /**

                     * $('#box').attr(undefined,function () {})

                     *

                     * fn = bulk = jQuery.attr;

                     *

                     * fn = function (elem, key, value) {

                     *  return jQuery.attr.call(jQuery(elem),value);

                     * }

                     *

                     */

                } else { //如果key有值的话,好办,这里的bulk是为了节省一个变量,将fn用bulk存起来,然后封装fn的调用

                    bulk = fn;

                    fn = function( elem, key, value ) {

                        return bulk.call( jQuery( elem ), value );

                    };

                }

            }

 

            //jQuery.access(elems,jQuery.attr,)

 

 

            //如果fn存在,掉调用每一个元素,无论key是否有值,都会走到这个判断,执行set动作

            if ( fn ) { // 递归调用之

                for ( ; i < length; i++ ) {

                    fn( elems[i], key,

                        raw ? value :

                        /**

                         * 如果value是原始数据,就取value,如果是个函数,就调用这个函数取值

                         * $('#box').attr('abc',function (index,value) { index指向当前元素的索引,value指向oldValue

                         *

                         *  先调用jQuery.attr(elements[i],key) 取到当前的值,然后调用传入的fn值

                         * });

                         */

 

 

                            value.call( elems[i], i, fn( elems[i], key ) )

                    );

                }

            }

        }

 

        /**

         * 如果chainable为true,说明是个set方法,就返回elems

         * 否则说明是get方法

         * 1.如果bulk是个true,说明没有key值,调用fn,将elems传进去

         * 2.如果bulk为false,说明key有值哦,然后判断元素的长度是否大于0

         *    2.1 如果大于0,调用fn,传入elems[0]和key,完成get

         *    2.2 如果为0,说明传参有问题,返回指定的空值emptyGet

         */

        return chainable ?

            elems :

 

            // Gets

            bulk ?

                fn.call( elems ) :

                length ? fn( elems[0], key ) : emptyGet;

    },

复制代码

 

 

ExtJS 中的flexSetter方法

这让我猛然想起了Ext的flexSetter方法,该方法在Ext.Function.flexSetter 详细API请看这里

 

用法:

 

复制代码

    var ele = document.getElementById('box');

 

    function setattribute(name, value) {

        ele.setAttribute(name, value);

    }

 

    var flexSetAttribute = Ext.Function.flexSetter(setAttribute);

 

    flexSetAttribute('title', '标题');

    flexSetAttribute({

        'abc': 'otherattribu',

        'other': 1

    });

复制代码

 

 

源码

 

复制代码

    /**

     * 1.关于Ext.enumerables的实现

     *

     * 这里为了兼容某些浏览器的toString,valueOf等内置方法不能被遍历出来的bug

     * var o = {toString:111,valueOf:222};

     *

     * for (var oo in o)

     * {

           alert(oo);

       }

     *

     */

    var enumerables = [//'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',

                'valueOf', 'toLocaleString', 'toString', 'constructor'];

 

    for (i in { toString: 1 }) {

        enumerables = null;

    }

 

    Ext.Function = {

        flexSetter: function(setter) {

            return function(name, value) { // 返回一个闭包

                var k, i;

 

                if (name !== null) {

                    if (typeof name !== 'string') { //如果name不是字符串,这里就认为是对象,进行for in

                        for (k in name) {

                            if (name.hasOwnProperty(k)) {

                                setter.call(this, k, name[k]); //逐个调用setter

                            }

                        }

 

                        if (Ext.enumerables) {

                            for (i = Ext.enumerables.length; i--;) {

                                k = Ext.enumerables[i];

                                if (name.hasOwnProperty(k)) {

                                    setter.call(this, k, name[k]);

                                }

                            }

                        }

                    } else {

                        setter.call(this, name, value); // 如果是个字符串,直接调用了

                    }

                }

 

                return this;

            };

        }

    };

复制代码

 

 

总结:很显然,Ext的flexSetter没有jQuery的强大,但是足够严谨,jQuery.access为prop、attr等上层需要灵活设置参数的功能做了一个统一的整理,方便了调用,节省了比特。

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-jQuery.access源码分析全部内容,希望文章能够帮你解决javascript代码实例教程-jQuery.access源码分析所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。