jQuery.access源碼分析

來源:互聯網
上載者:User

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,並將是否可以鏈式調用的標誌位設定為true2.判斷value值是否已經定義,如果已經定義,說明是個set操作2.1 set操作的是可鏈式調用的2.2 如果value不是function,設定raw為true2.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等上層需要靈活設定參數的功能做了一個統一的整理,方便了調用,節省了位元。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.