jQuery屬性操作之.attr()

来源:https://www.cnblogs.com/peterzhangsnail/archive/2018/11/28/10030013.html
-Advertisement-
Play Games

轉載請註明出處 @[toc] .attr() 1. .attr() 的四種用法 大致用法: 調用形式:$("xxx").attr(attrName); 獲取匹配到的所有元素中的第一個元素的指定屬性的屬性值. 調用形式:$("xxx").attr(attrName,value): 設置/新增匹配到的所 ...


目錄

轉載請註明出處

@

.attr()

1..attr()的四種用法
大致用法:

  • 調用形式:$("xxx").attr(attrName);
    獲取匹配到的所有元素中的第一個元素的指定屬性的屬性值.
  • 調用形式:$("xxx").attr(attrName,value):
    • 設置/新增匹配到的所有元素的指定屬性的屬性值
    • 如果value=null,指定屬性將被刪除
  • 調用形式:$("xxx").attr(attrObject):
    用"屬性-值"的鍵值對構成的對象來設置匹配到的所有元素的一個或多個屬性.
  • 調用形式:$("xxx").attr(attrName,attrFn(index,val)):
    用一個函數attrFn的返回值作為value來設置某一個匹配元素的指定屬性.(attrFn函數的參數有明確規定:index--該匹配元素在jQuery對象中的index值,也就是它的鍵值.attr--當前該元素的該屬性的值(舊值))

用法詳解:
(1)..attr()源代碼定義:

jQuery.fn.extend( {
    attr: function( name, value ) {
        return access( this, jQuery.attr, name, value, arguments.length > 1 );
    }
}

可見,.attr的核心是函數access(),而該函數不需要實例即可調用,屬於直接定義在jQuery上的'靜態函數'.

jQuery.access()源代碼定義:

var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
    var i = 0,
        length = elems.length,
        bulk = key == null; //bulk用於判斷key值是否為null(註:null==undefined的結果為true)

    // 設置多個值(當key參數為對象時,註:jQuery.type實現原理是[[class]])
    if ( jQuery.type( key ) === "object" ) {
        chainable = true;
        for ( i in key ) {
            access( elems, fn, i, key[ i ], true, emptyGet, raw );
        }

    // 設置一個值(當key為非對象類型時)
    } else if ( value !== undefined ) {
        chainable = true;

        if ( !jQuery.isFunction( value ) ) {
            raw = true; //判斷value值是否為函數類型.如果不是函數,設置raw值,為if(fn)以及if(bulk)埋下伏筆
        }

        if ( bulk ) { //當傳入key值為null時的處理情況(這段代碼,我們在分析.attr()時不會用到)

            // Bulk operations run against the entire set
            if ( raw ) {
                fn.call( elems, value );
                fn = null;

            // ...except when executing function values
            } else {
                bulk = fn;
                fn = function( elem, key, value ) {
                    return bulk.call( jQuery( elem ), value );
                };
            }
        }

        if ( fn ) { //對elems中的每一個元素應用fn方法,第三個參數由raw決定
            for ( ; i < length; i++ ) {
                fn(
                    elems[ i ],
                    key,
                    raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) )
                );
            }
        }
    }

    return chainable ? //返回值設定
        elems :

        // Gets
        bulk ?
            fn.call( elems ) :
            length ? fn( elems[ 0 ], key ) : emptyGet;
}

如上圖,由於access函數用途並不局限於我們的.attr(),作為像筆者一樣的jQuery初學者,源代碼中有許多代碼語句我們不能很好的理解(比如:if(bulk)部分).由於暫時接觸到的jQuery內容較少較淺,我們如果一味深究,可能既搞不清楚原理,還浪費時間.所以,我們可以用一種簡化的思想來分析問題: 只關註代碼中跟我們當前問題有關的部分,忽略無關的,用不到的部分.

具體做法:我們將.attr()的四種用法的實際傳參情況帶入jQuery.access函數的定義中,刪除我們進不去的if語句代碼塊,只保留會用到的代碼語句.


調用形式:$("xxx").attr(name)

attr定義:

attr: function( name, value=undefined ) {
    return jQuery.access( this, jQuery.attr, name, value=undefined, arguments.length > 1 );
}

access調用簡化:

var access = function( this, jQuery.attr, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //jQuery對象的length屬性(jQuery對象總是有length屬性,它是類數組對象)
        bulk = false;

    return jQuery.attr( this[0], name );
    };   

同樣,我們找到jQuery.attr()靜態方法的源代碼定義,用同樣的簡化方法分析,得到:

jQuery.attr()完整源碼:

attr: function( elem, name, value ) {  // elem:DOM對象  name:屬性名/鍵名 value:屬性值
    var ret, hooks,
        nType = elem.nodeType;  // 節點類型

    // 屏蔽屬性節點,文本節點與註釋節點
    if ( nType === 3 || nType === 8 || nType === 2 ) {
        return; 
    }

    // 當屬性不支持getAttribute方法時,回調jQuery.prop()方法--從操作attribute變成了操作property
    if ( typeof elem.getAttribute === "undefined" ) {
        return jQuery.prop( elem, name, value );
    }


//下麵的都是DOM元素elem支持getAttribute的情況

    // 所有標簽特性(attributes)都是小寫(處理相容:有的瀏覽器對同一屬性的名稱可能大小寫不停)
    // 如果某一個是已定義的,抓取必要的鉤子

    if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {  // 非元素節點或者是XML文本中的元素
        name = name.toLowerCase();
        hooks = jQuery.attrHooks[ name ] ||  
            ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); 
    }

    if ( value !== undefined ) {//如果value在傳參時未被忽略
        if ( value === null ) {
            jQuery.removeAttr( elem, name );//傳入第三個參數為null時,調用jQuery.removeAttr移除對應屬性
            return;
        }

        if ( hooks && "set" in hooks && 
            ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
            return ret;
        }

        elem.setAttribute( name, value + "" );
        return value;
    }

    if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
        return ret;
    }

    ret = jQuery.find.attr( elem, name );

    // 不存在的屬性會返回null,我們將之統一為undefined
    return ret == null ? undefined : ret;
}

jQuery.attr()簡化:

attr: function( elem, name, value=undefined ) {  // elem:DOM對象  name:屬性名/鍵名 value:屬性值
    var ret, hooks,
        nType = 1;

    ret = jQuery.find.attr( elem, name );

    return ret;
}   

其中,唯一不確定的是jQuery.find.attr,然而我們繼續找下去則是有關Sizzle選擇器引擎的問題,這對於我們初學者來說過於複雜.因此,我們再簡化一下,帶入實際情景,檢測這一函數的輸出:

var $p = $('#jQueryTest')[0];

console.log(jQuery.find.attr($p,'id')); //jQueryTest   

因此,大概知道該函數該種傳參情況下的作用是返回指定DOM元素的指定屬性的值.
1.由jQuery.access簡化代碼中的return jQuery.attr( this[0], name );可知,只傳入一個name參數的情況下,確實只會返回jQuery對象中的索引為'0'的DOM對象的指定屬性的屬性值.
2.由jQuery.att()完整代碼中
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}

可知:如果不支持get/setAttibute,那麼原來的針對特性(attibute)的操作就會變成DOM元素屬性(property)的操作.


調用形式:$("xxx").attr(name,value);

attr定義:

attr: function( name, value) {  //此時的this是一個類數組
        return jQuery.access( this, fn=jQuery.attr, name, value, chainable=true);
    }

access調用簡化:

var access = function( this, jQuery.attr, name, value, chainable=true, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //jQuery對象的length屬性,表示找到的匹配的DOM元素的個數
        bulk = false;


        chainable = true;

        if ( !jQuery.isFunction( value ) ) { //當value值不為函數時,設置raw為true,這是為了下一步if(jQuery.attr)中的raw判斷做鋪墊
            raw = true; 
        }

        
        if ( jQuery.attr ) { //jQuery.attr,為true

            for ( ; i < length; i++ ) {  //用for迴圈是因為此時的this是一個包含多個DOM元素的jQuery對象
                jQuery.attr(
                    this[ i ],
                    name,
                    raw ? value : value.call( elems[ i ], i, jQuery.attr( this[ i ], name ) )                       
                );//raw為true,也就是value不為函數時,用value作第三參數
            }     
        }
    }

    return this; //返回jQuery對象本身

};

而,我們用簡化的方法分析此種情況下的jQuery.attr(this,name,value):

attr: function( this[i], name, value ) {
    var ret, hooks,
        nType = this[i].nodeType;

    if ( value !== undefined ) {  //判斷為true,進入if語句
        if ( value === null ) {
            jQuery.removeAttr( this[i], name );//如果value為null,刪除該jQuery對象的所有匹配元素的指定屬性
            return;
        }

        this[i].setAttribute( name, value + "" );//設置當前DOM元素的指定屬性的屬性值
        return value;
    }

    ret = jQuery.find.attr( this[i], name ); //刪除了屬性,返回null;否則,返回指定屬性的屬性值

    return ret == null ? undefined : ret; //如果刪除了指定屬性,返回undefined;如果修改了屬性,返回指定屬性值
}

調用形式:$("xxx").attr(attrObject);

attr定義:

attr: function( name=attrObject ) {
        return jQuery.access( this, jQuery.attr, name=attrObject, value=undefined, false);
    }

access調用簡化:

var access = function( this, fn, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //元素的length屬性
        bulk = false;

    // 設置多個value值
    if ( jQuery.type( name ) === "object" ) { //如果傳入的name形參為對象類型
        chainable = true;
        for ( i in name ) { //對每一個對象中的屬性名及屬性值再次調用本身(遞歸)
            access( this, fn, i, name[ i ], true, emptyGet, raw );
        }

    }
    return elems;  //返回jQuery對象本身

};   

可見,對於一個由"屬性-屬性值"鍵值對構成的對象,會對其中的每一個屬性都調用access設置一次.由於代碼中使用的for-in迴圈,所以enumerable為false的鍵值對是無效的.


調用形式:$("xxx").attr(name,attrFn);

attr定義:

attr: function( name, value=attrFn ) {
        return jQuery.access( this, jQuery.attr, name, value=attrFn, chainable=true );
    }

access調用簡化:

var access = function( this, jQuery.attr, name, value=attrFn, chainable=true, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //jQuery對象的length屬性
        bulk = false;

        chainable = true;

        if ( jQuery.attr ) {  //true,進入if語句
            for ( ; i < length; i++ ) {
                jQuery.attr(
                    this[ i ],
                    name,
                    attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) )  // 調用attrFn,其返回值作為第三個參數                                             
                );
            }
        }

    return elems; // 返回jQuery對象本身
};

attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) )可知,attrFn的參數限制就是源自這一行代碼:(this[i]是調用attrFn的元素,後面兩個是參數,一個是jQuery對象中的索引值,一個是當前元素的指定屬性name的值的查詢返回)

[特別註意:attrFn的兩個參數雖然有規定,但是不需要我們真的傳參,而是函數體內部使用索引值或者當前屬性值的一個介面]


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 主流的APP都少不了跟伺服器交互,網路請求是少不了的事情。 開源的網路請求庫,有很多,比如:AFNetworking、YTKNetwork、PPNetworkHelper、ASIHttpRequest,等等。 ...
  • 可以看出來使用兩個參數時,它的內部也是調用了3個參數的方法。 如果我們使用LayoutInflater.from(context).inflate(R.layout.recycle_foot_item,null); 則實際上是調用了LayoutInflater.from(context).infla ...
  • 我的Android studio版本是2.2版本 1.Ctrl+z是撤銷快捷鍵 2.如果Ctrl+z 掉的內容,又反悔了,快捷鍵為:Ctrl + Shift + z。 ...
  • 一,效果圖。 二,代碼。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>javascript 變數</title> </head> <body> <script> var x = 5; var y = 6; var z = x ...
  • 1.偽類與偽元素的區別? 1) 定義區別 2) 語法區別 3) 偽類/偽元素一覽表 2. css樣式優先順序,各自的權重 3.常見的DOM操作有哪些? 主要操作包括:查找節點,新建節點,添加節點,刪除節點,修改節點;開發中,我們用到最多的是element類型,用於表現HTML元素,提供了對元素標簽名、 ...
  • 轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 【年末促銷】葡萄城 2018 歲末福利火熱放送中 原文轉載自 微信公眾號 justjavac 早起看手機,結果發現我的微信群炸了,未讀消息 999+,大家都在討論 event-stream 事件。打開 twi ...
  • 1.問題起源 在平時的業務開發寫CSS中,為了滿足頁面佈局,元素的浮動特性我們用的不能再多了。使用浮動的確能夠解決一些佈局問題,但是也帶了一些副作用影響,比如,父元素高度塌陷,我們有好幾種可以清除浮動的方法,最常用的就是設置父元素的overflow:hidden這個屬性,每次在寫代碼的時候總是這樣寫 ...
  • 網上的相關教程非常多,基礎知識自行搜索即可。 習題主要選自Orelly出版的《數據結構與演算法javascript描述》一書。 參考代碼可見: "https://github.com/dashnowords/blogs/tree/master/Structure/graph" 一.圖的基本知識 基本概 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...