JS獲取元素的N種方法及其動靜態(tài)討論

實際前端開發(fā)工作中泌参,我們經(jīng)常會遇到要獲取某些元素霎桅,以達到更新該元素的樣式旅择、內(nèi)容等目的宣赔。而文檔對象模型 (DOM) 是HTML和XML文檔的編程接口预麸,它提供了對文檔的結(jié)構(gòu)化的表述,并定義了一種方式可以從程序中對該結(jié)構(gòu)進行訪問儒将,從而改變文檔的結(jié)構(gòu)吏祸,樣式和內(nèi)容。DOM 將文檔解析為一個由節(jié)點和對象(包含屬性和方法的對象)組成的結(jié)構(gòu)集合钩蚊,它會將web頁面和腳本或程序語言連接起來贡翘。也因此蹈矮,JavaScript可以通過DOM API獲取元素節(jié)點,方法有如下幾種:其中querySelector()querySelectorAll()為ES5的元素選擇方法

1床估、getElementById():

接收一個參數(shù):要取得的元素的ID(區(qū)分大小寫含滴,必須嚴格匹配)诱渤,返回一個Element對象(也可看作是動態(tài)NodeList集合丐巫,只是集合中只包含一個匹配的元素,但也會實時反映DOM節(jié)點的變化)勺美,若當前文檔中擁有特定ID的元素不存在則返回nul递胧。
語法:

element = document.getElementById(id);

示例:刪除

<body>
    <div id="myDiv">
        <p class="myP">hello world</p>
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>
    <script>
        var div = document.getElementById("myDiv");
        console.log(div); //(1)
        var body=document.querySelector('body');
        body.removeChild(div);
        console.log(body); //(2)
    </script>
</body>
//(1)處打印值
    <div id="myDiv">
        <p class="myP">hello world</p>
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>

//(2)處打印值
<body>
    <script>
        var div = document.getElementById("myDiv");
        console.log(div); //(1)
        var body=document.querySelector('body');
        body.removeChild(div);
        console.log(body); //(2)
    </script>
</body>

示例:

<!DOCTYPE html>
<html>
<head>
  <title>getElementById example</title>
  <script>
  function changeColor(newColor) {
    var elem = document.getElementById("para1");
    elem.style.color = newColor;
  }
  </script>
</head>
<body>
  <p id="para1">Some text here</p>
  <button onclick="changeColor('blue');">blue</button>
  <button onclick="changeColor('red');">red</button>
</body>
</html>

getElementById()方法不會搜索不在文檔中的元素。當創(chuàng)建一個元素且分配ID后赡茸,必須要使用insertBefore()或其他類似的方法把元素插入到文檔中之后才能使用 getElementById() 獲取到:

var element = document.createElement("div");
element.id = 'testqq';
var el = document.getElementById('testqq'); // el will be null!

2缎脾、getElementsByClassName():

接收一個參數(shù),即包含一個或多個類名的字符串(類名通過空格分隔)占卧,返回一個HTMLCollection動態(tài)集合(也可以說返回一個NodeList類數(shù)組對象),集合中包含以當前元素為根節(jié)點,所有指定 class 名的子元素恰画。
語法:

var elements = document.getElementsByClassName(names); 
var elements = rootElement.getElementsByClassName(names);

getElementsByClassName 可以在任意的元素上調(diào)用看彼,不僅僅是document。 調(diào)用這個方法的元素將作為本次查找的根元素叭喜。
示例:

  • 獲取所有 class 為 'test' 的元素:
document.getElementsByClassName('test');
  • 獲取所有 class 同時包括 'red' 和 'test' 的元素:
document.getElementsByClassName('red test');
  • 在id 為'main'的元素的子節(jié)點中贺拣,獲取所有class為'test'的元素:
document.getElementById('main').getElementsByClassName('test');

示例:刪除

//html代碼
<div class="myDiv">
        <p class="myP">hello world</p>
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>
//js代碼一
    <script>
        var div = document.getElementsByClassName("myDiv");
        console.log(div); //(3)
        var p = document.getElementsByClassName("myP");
        for (var i = 0; i < p.length; i++) {
            div[0].removeChild(p[i]);
        }
        console.log(p); //(4)
    </script>
//(3)處打印值
[div.myDiv] //一個動態(tài)的HTMLCollection集合,長度為1捂蕴,innerHTML為<p class="myP">hello dolby</p>譬涡,<p class="myP">hello bean</p>,為什么沒有其他兩個p元素一會兒解釋啥辨。

//(4)處打印值
[p.myP,p.myP] //一個動態(tài)的HTMLCollection集合涡匀,長度為2,innerHTML分別為"hello dolby"溉知,"hello bean"陨瘩。

以上用刪除節(jié)點的方法驗證了getElementsByClassName方法返回的是一個HTMLCollection動態(tài)集合。

??以上代碼中着倾,首先div取得了頁面中類名為"myDiv"的元素組成的動態(tài)集合拾酝,p取得了頁面中類名為"myP"的元素組成的動態(tài)集合,接著用一個for循環(huán)來刪除"myDiv"集合中第一項(即上例中唯一的div元素)中的"myP"集合中的每一項卡者,結(jié)果只有第一項和第三項被刪除了蒿囤,這是為什么呢?
原因是動態(tài)集合中DOM結(jié)構(gòu)的變化能夠自動反映到所保存的對象中崇决,最開始p.legth=4材诽,當i=0時刪除了頁面中第一個p元素底挫,此后p.length=3;i=1時刪除了剩余的三個p中的項目索引為1的項脸侥,此后p.length=2建邓;i=2時已不滿足i<p.length這一條件,所以不會繼續(xù)執(zhí)行循環(huán)睁枕。至此只刪除了頁面上的第一和第三個p元素官边,所以打印p得到了一個長度為2的HTMLCollection動態(tài)集合,其中包含"hello dolby"和"hello bean"外遇,p的變化也實時反映到了動態(tài)集合div中注簿,所以才有(1)處的打印結(jié)果。

那么怎樣才能遍歷類數(shù)組對象HTMLCollection集合中的每一項并且刪除所有項呢跳仿?
還是一個for循環(huán)搞定??诡渴,每次刪除對象集合中的最后一項就可以啦~

//js代碼二
    <script>
        var div = document.getElementsByClassName("myDiv")[0];
        console.log(div); //(5)
        var p = document.getElementsByClassName("myP");
        for (var i=p.length;i--;){
            div.removeChild(p[i]);
        }
        console.log(p); //(6)
    </script>
//(5)處打印值
<div class="myDiv"></div>

//(6)處打印值
[] //空的HTMLCollection集合,長度為0

3菲语、getElementsByTagName():

接收一個參數(shù):要取得的元素的標簽名(不區(qū)分大小寫)妄辩,返回一個HTMLCollection動態(tài)集合(也可以說返回一個NodeList類數(shù)組對象),集合中包含以當前元素為根節(jié)點(不包括當前元素自身),所有指定標簽名的子元素山上,子元素的順序是在當前元素的子樹中出現(xiàn)的順序眼耀,如果沒有搜索到元素則集合為空。
語法:

elements = element.getElementsByTagName(tagName)

示例:

// check the alignment on a number of cells in a table. 
var table = document.getElementById("forecast-table"); 
var cells = table.getElementsByTagName("td"); 
for (var i = 0; i < cells.length; i++) { 
    var status = cells[i].getAttribute("data-status"); 
    if ( status == "open" ) { 
        // grab the data 
    }
}

示例:刪除

<body>
    <div id="myDiv">
        <p class="myP">hello world</p>
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>
    <script>
        var div = document.getElementById("myDiv");
        console.log(div); //(7)
        var p = document.getElementsByTagName("p");
//以下for循環(huán)改為for (var i=0,len=p.length;i<len;i++) {div.removeChild(p[0]);}也可胶哲;將集合p的長度賦值給變量len畔塔,這樣len就是一個固定值,每次都刪除當前集合項目索引為0的項鸯屿,就可以循環(huán)遍歷刪除掉集合里的所有項澈吨。
        for (var i=p.length;i--;){
            div.removeChild(p[i]);
        }
        console.log(p); //(8)
    </script>
</body>

與getElementByClassName相同,返回動態(tài)集合寄摆,所以循環(huán)刪除結(jié)果也相同

//(7)處打印值
<div id="myDiv"></div>

//(8)處打印值
[] //空的HTMLCollection集合谅辣,長度為0

4、getElementsByName():

接收一個參數(shù):帶有給定name屬性值的元素婶恼,返回一個動態(tài)NodeList類數(shù)組對象桑阶,對象中包含以當前元素為根節(jié)點,所有指定name屬性值的子元素勾邦。最常用的場景是取得單選按鈕蚣录。
示例:

<!DOCTYPE html>
<html lang="en">
<head>
 ...
</head>

<body>
<form name="up"><input type="text"></form>
<div name="down"><input type="text"></div>

<script>
var up_forms = document.getElementsByName("up");
console.log(up_forms[0].tagName); // returns "FORM"
</script>
</body>
</html>

示例:刪除

<body>
    <div id="myDiv">
        <input type="radio" name="fav-color">red
        <input type="radio" name="fav-color">green
        <input type="radio" name="fav-color">blue
    </div>
    <script>
        var div = document.getElementById("myDiv");
        console.log(div); //(9)
        var ipt_favCol = document.getElementsByName("fav-color");
        for (var i = ipt_favCol.length; i--;) {
            div.removeChild(ipt_favCol[i]);
        }
        console.log(ipt_favCol); //(10)
    </script>
</body>

getElementByName返回的是一個NodeList動態(tài)集合

//(9)處打印值
<div id="myDiv">
"red"
"green"
"blue"
</div>

//(10)處打印值
[] //空的NodeList集合,長度為0

5眷篇、querySelector():

接收一個參數(shù):一個包含一個或多個CSS 選擇器的字符串(多個選擇器以逗號分隔)萎河,返回匹配指定CSS選擇器的第一個元素節(jié)點(無法選中CSS偽元素),沒有發(fā)現(xiàn)匹配的節(jié)點則返回null。
語法:

element = document.querySelector(selectors);

示例:一個強大的選擇方式

<div class="user-panel main">
    <input name="login"/> //這個標簽將被返回
</div>

<script>
    var el = document.querySelector("div.user-panel.main input[name=login]");
</script>

示例:如果要匹配的ID或選擇器不符合 CSS 語法(比如不恰當?shù)厥褂昧嗣疤柣蛘呖崭瘢┡氨惚仨氂梅葱备軐⑦@些字符轉(zhuǎn)義玛歌。由于 JavaScript 中,反斜杠是轉(zhuǎn)義字符擎椰,所以當你輸入一個文本串時支子,你必須將它轉(zhuǎn)義兩次(一次是為 JavaScript 字符串轉(zhuǎn)義,另一次是為 querySelector 轉(zhuǎn)義):

<div id="foo\bar"></div>
<div id="foo:bar"></div>

<script>
  console.log('#foo\bar')               // "#fooar"
  document.querySelector('#foo\bar')    // 不匹配任何元素

  console.log('#foo\\bar')              // "#foo\bar"
  console.log('#foo\\\\bar')            // "#foo\\bar"
  document.querySelector('#foo\\\\bar') // 匹配第一個div

  document.querySelector('#foo:bar')    // 不匹配任何元素
  document.querySelector('#foo\\:bar')  // 匹配第二個div
</script>

示例:刪除

    <div id="myDiv">
        <p class="myP">hello world</p>
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>
    <script>
        var div = document.getElementById("myDiv");
        console.log(div); //(11)
        var p = document.querySelector("p");
        div.removeChild(p);
        console.log(p); //(12)
    </script>
//(11)處打印值
    <div id="myDiv">
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>

//(12)處打印值
        <p class="myP">hello world</p> //如你所見达舒,querySelector也是靜態(tài)的快照

6值朋、querySelectorAll():

接收一個參數(shù):一個包含一個或多個CSS 選擇器的字符串(多個選擇器以逗號分隔),返回靜態(tài)NodeList對象集合休弃,該集合中包含匹配指定CSS選擇器的所有節(jié)點吞歼,元素節(jié)點的變化無法實時反映在結(jié)果中;如果參數(shù)中包含CSS偽元素則返回一個空的對象集合塔猾。
語法:

elementList = document.querySelectorAll(selectors);

示例:

var matches = document.querySelectorAll("div.note, div.alert");

示例:刪除

    <div id="myDiv">
        <p class="myP">hello world</p>
        <p class="myP">hello dolby</p>
        <p class="myP">hello dot</p>
        <p class="myP">hello bean</p>
    </div>
    <script>
        var div = document.getElementById("myDiv");
        console.log(div); //(13)
        var p = document.querySelectorAll("p");
        for (var i = 0; i < p.length; i++) {
            div.removeChild(p[i]);
        }
        console.log(p); //(14)
    </script>
//(13)處打印值
    <div id="myDiv"></div>
//(13)處打印值
    [p.myP,p.myP,p.myP,p.myP] //返回的是靜態(tài)NodeList集合,元素節(jié)點的變化無法實時反映在結(jié)果中

7稽坤、elementFromPoint():

接收兩個參數(shù):分別是相對于當前窗口左上角的橫縱坐標丈甸,單位為CSS像素,不需要加單位尿褪;返回位于頁面指定位置的元素睦擂,如果該元素不可返回(如滾動條)則返回它的父元素,如果坐標值無意義(如負值)則返回null杖玲。
語法

var element = document.elementFromPoint(x, y);

示例:

<!DOCTYPE html>
<html lang="en">
<head>
<title>elementFromPoint example</title>

<script>
function changeColor(newColor) {
  elem = document.elementFromPoint(2, 2);
  elem.style.color = newColor;
}
</script>
</head>

<body>
<p id="para1">Some text here</p>
<button onclick="changeColor('blue');">blue</button>
<button onclick="changeColor('red');">red</button>
</body>
</html>

這一個獲取元素的方法用得不多所以不多做介紹顿仇。


是不是覺得看了上面這些頭好大啊,什么是動態(tài)什么是靜態(tài)摆马,有沒有好記一點的方法呢臼闻?
有噠!

你可以簡單地理解為囤采,getElementBy系列返回的都是動態(tài)的HTMLCollection集合述呐,動態(tài)集合中的DOM結(jié)構(gòu)變化能實時地反映到所保存的對象中,而querySelector系列返回的都是靜態(tài)的NodeList對象蕉毯,是一個快照乓搬,對DOM的任何操作都不會對其產(chǎn)生影響。

那么Nodelist和HTMLCollection有什么異同呢代虾?

相同點:

  • 二者都是類數(shù)組對象
  • 二者都具有l(wèi)ength屬性
  • 二者都具有item()方法
  • 二者都是動態(tài)的元素集合进肯,每次訪問都需要重新對文檔進行查詢。

你一定會好奇棉磨,誒江掩?前面不是說querySelector系列返回的都是靜態(tài)的NodeList對象咩?怎么又變成動態(tài)的呢?原因在此:
規(guī)范中對 querySelectorAll 有明確要求频敛,規(guī)定其必須返回一個靜態(tài)的 NodeList 對象项郊。
在Chrome中情況如下:

document.querySelectorAll('a').toString();    // return "[object NodeList]"
document.getElementsByTagName('a').toString();    // return "[object HTMLCollection]"

不同點:

  • NodeList 對象會包含文檔中的所有節(jié)點,如 Element斟赚、Text 和 Comment 等着降;HTMLCollection 對象只會包含文檔中的 Element 節(jié)點。

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市发侵,隨后出現(xiàn)的幾起案子交掏,更是在濱河造成了極大的恐慌,老刑警劉巖刃鳄,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盅弛,死亡現(xiàn)場離奇詭異,居然都是意外死亡叔锐,警方通過查閱死者的電腦和手機挪鹏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愉烙,“玉大人讨盒,你說我怎么就攤上這事〔皆穑” “怎么了返顺?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔓肯。 經(jīng)常有香客問我遂鹊,道長,這世上最難降的妖魔是什么省核? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任稿辙,我火速辦了婚禮,結(jié)果婚禮上气忠,老公的妹妹穿的比我還像新娘邻储。我一直安慰自己,他們只是感情好旧噪,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布吨娜。 她就那樣靜靜地躺著,像睡著了一般淘钟。 火紅的嫁衣襯著肌膚如雪宦赠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機與錄音勾扭,去河邊找鬼毡琉。 笑死,一個胖子當著我的面吹牛妙色,可吹牛的內(nèi)容都是我干的桅滋。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼身辨,長吁一口氣:“原來是場噩夢啊……” “哼丐谋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起煌珊,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤号俐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后定庵,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吏饿,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年洗贰,在試婚紗的時候發(fā)現(xiàn)自己被綠了找岖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡敛滋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兴革,到底是詐尸還是另有隱情绎晃,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布杂曲,位于F島的核電站庶艾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏擎勘。R本人自食惡果不足惜咱揍,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棚饵。 院中可真熱鬧煤裙,春花似錦、人聲如沸噪漾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽欣硼。三九已至题翰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豹障。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工冯事, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人血公。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓昵仅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坞笙。 傳聞我的和親對象是個殘疾皇子岩饼,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容