以前咱們已經講過,style用於在JS裏控制元素的樣式,經過style能夠選中元素的各類css屬性。此外,咱們也提到過,JS用className控制元素的class。這二者之間,是否會產生什麼矛盾嗎?css
咱們使用一段簡單的代碼做爲示例:html
<html> <head> <meta charset="utf-8"> <title>無標題文檔</title> <style> #div1 {width:200px; height:200px; border:1px solid black;} .box {background:red;} </style> <script> function toRed() { var oDiv=document.getElementById('div1'); oDiv.style.background='red'; } </script> </head> <body> <input type="button" value="變紅" onclick="toRed()" /> <div id="div1"></div> </body> </html>
這段代碼的做用沒必要多說,點擊變紅按鈕後,div1塊的背景顏色會變爲紅色。如今咱們打開瀏覽器的控制檯(F12),選中Div1,觀察點擊先後的變化:前端
能夠看到,JS對div1的樣式其實是經過行間樣式的方法進行控制的。實際上,經過JS的style方法加入的樣式都是經過行間樣式來控制的,並且經過style也只能讀取到元素的行間樣式。數組
咱們來看看style和class之間的關係。要闡明這二者之間的關係,首先須要弄清楚css裏的樣式優先級。在css裏,樣式的優先級表明了css優先執行的代碼。樣式優先級的順序以下(從高到低):瀏覽器
行間樣式具備最高的優先級。如今咱們來看這個一個例子:函數
<html> <head> <meta charset="utf-8"> <title>無標題文檔</title> <style> #div1 {width:200px; height:200px; border:1px solid black;} .box {background:red;} </style> <script> function toRed() { var oDiv=document.getElementById('div1'); oDiv.className='box'; } function toGreen() { var oDiv=document.getElementById('div1'); oDiv.style.background='green'; } </script> </head> <body> <input type="button" value="變紅" onclick="toRed()" /> <input type="button" value="變綠" onclick="toGreen()" /> <div id="div1"></div> </body> </html>
上述代碼先執行toRed函數再執行toGreen函數,程序能夠正常運行;但若是先執行toGreen函數再執行toRed函數,toRed函數會失效。緣由在於點擊toGreen函數後,background爲green屬性的css添加到了行間,而點擊toRed函數,雖然也能給元素添加含有background爲red屬性的class,但由於行間樣式優先級比class高,因此優先執行行間樣式的代碼。咱們能夠獲得以下結論:對於同一元素的同一屬性,若是修改了其style,以後再修改其className不會再有效果。所以咱們建議,對於同一個元素,在操做上保持一致性,要麼只操做它的style,要麼只操做它的className。htm
咱們以前使用的onclick="toGreen()"這一類寫法就被叫作行間事件。然而,在咱們實際工做的時候,一個頁面一般是由多我的完成,若是將事件寫在行間有可能會出現編輯的時候事件被刪掉的狀況。並且,當須要給大量元素增添功能相同的事件時,使用行間事件顯得太過麻煩和重複。若元素的數量不固定,使用行間事件更是對代碼無從下手。而採用提取行間事件的方法,能夠很好地解決這些問題。blog
說到提取行間事件,咱們首先得提到如何用JS給元素添加事件。能夠看到,行間事件onclick的寫法讓onclick顯得很像一個屬性,那麼是否能夠經過操縱屬性的方法將行間事件寫到函數裏呢?固然是能夠的,咱們將以前例子的一些代碼進行修改:事件
var oBtn=document.getElementById('btn1'); function abc(){ alert('a'); } oBtn.onclick=abc;
效果和使用行間事件沒有任何區別。這就是最簡單的提取行間事件的方法。
在寫網頁代碼的時候,若是代碼量過大或者函數過多,取函數名是一件很是頭疼的事情。在JS裏,提供了一種匿名函數的形式,這種寫法不用給函數取名,而函數體須要放在調用函數的地方。咱們能夠將上面的代碼改爲以下形式:
var oBtn=document.getElementById('btn1'); oBtn.onclick=function () //匿名函數 { alert('a'); };
實際工做中,大部分的事件都是經過這種匿名函數的方式完成的,這樣很是方便,不會出現忘記函數名的狀況。
JS代碼在瀏覽器執行的時候,有一個特色:每讀一行,執行一行。在咱們上面的例子中,咱們將script標籤放在了body裏,程序能夠正常執行。但若是你試着將script標籤放在head標籤裏,你會發現程序報錯。緣由在於,當瀏覽器讀到oBtn.onclick這一行時,後面body的代碼尚未被加載進來,所以實際上你是在給一個不存在的按鈕添加onclick事件,天然就會出錯了。如何解決這個問題呢?
這個問題能夠用window.onload事件解決。這個事件表明的含義是,當頁面加載完成的時候發生。咱們在前面的代碼外套加window.onload:
window.onload=function (){ var oBtn=document.getElementById('btn1'); oBtn.onclick=function () { alert('a'); } };
添加以後,window.onload內包裹的函數只在頁面加載結束後執行,所以函數執行的時候btn1已結被加載了進來,這樣程序就不會出錯了。
在前端領域來講,行爲,樣式,結構三者分別對應着JavaScript,css和HTML,而將行爲,樣式,結構三者分離,簡單來講,就是避免添加行間樣式和行間事件。咱們以前採用提取行間事件的方法將寫成函數就是這個目的,在從此的代碼編寫中,也建議你們儘可能遵照這個原則。
咱們以前提到,若是頁面須要給大量元素添加事件,使用咱們以前的寫法會讓代碼顯得很是繁雜重複。使用getElementsByTagName方法獲取元素能夠避免這一點。和getElementById方法不一樣的是,getElementById一次只能獲取一個元素(由於id在HTML裏不可重複),而getElementsByTagName一次能夠獲取一組元素。
爲了說明這個問題,咱們再舉一個小例子:
<html>
<head>
<meta charset="utf-8">
<title>無標題文檔</title>
<style>
div {width:200px; height:200px; float:left; border:1px solid black; margin:10px;}
</style>
<script>
window.onload=function ()
{
var aDiv=document.getElementsByTagName('div');
alert(aDiv.length);
};
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>
咱們經過getElementsByTagName得到了全部標籤名爲div的元素,而此時aDiv再也不是一個元素而是一個數組。數組的簡單概念能夠理解爲一堆元素的集合。數組有一個最簡單的屬性:length,表明了數組長度(元素個數),所以上面的例子中最後會彈出div塊的個數。所以結果以下:
一樣的,若是咱們想修改這些div的樣式,是否能夠直接利用getElementsByTagName獲取後直接修改呢?:
var aDiv = getElementsByTagName('div'); aDiv.style.background = 'red';
這樣的寫法是會出錯的。緣由在於在JS裏,一次只能對一個元素的屬性進行設置,而aDiv是一個數組,內含多個元素,沒法對其進行直接操做。爲了對數組進行操做,咱們須要瞭解如何得到數組內的單個元素。咱們若是將上面的代碼進行這樣的修改:
var aDiv = getElementsByTagName('div'); aDiv[0].style.background='red';
能夠看到,第一個div塊變爲了紅色。aDiv[0]中的0被稱爲下標,表明數組中元素的位數,須要注意的是下標統一是從0開始,aDiv[0]表明了aDiv數組中的第一個元素。
var aDiv = getElementsByTagName('div'); aDiv[0].style.background='red'; aDiv[1].style.background='red'; aDiv[2].style.background='red'; aDiv[3].style.background='red';
這樣就能把4個div塊的顏色都進行改變,但設置元素樣式的代碼依舊很是繁瑣,若是存在100個這樣的div,是否就須要將這樣的代碼寫100次?其實是不須要的,爲了可以把這些相似的代碼合併掉,咱們須要用到循環。
說到循環,咱們先來回憶一下咱們學過的if語句。還記得if語句的格式以下:
if(條件){ 語句1 } else{ 語句2 }
對於if語句來講,若是條件是成立的,會執行一次語句1,不然執行一次語句2。然而,若是咱們想屢次執行語句1呢?採用循環的方式即可以讓一個語句進行屢次執行。 第一種循環(while循環)的語句格式以下:
while(條件){ 語句 }
對於while循環來講,只要條件成立,語句會一直執行,直到條件再也不成立。咱們用例子說明:
var i = 0; //初始化 while (i < 5) { //條件 alert(i); //語句 i = i + 1 //自增 }
i=i+1的意思是將i的值加1再返回給自身,也就是說,循環每執行一次,i的大小就增長1。執行的結果以下:
當第一次執行完畢後,i的值變爲了1,依然比5小,因此繼續執行,這樣再反覆四次後,i的值變爲了5,5=5,條件再也不成立,因此跳出了循環。對於一個循環,一般須要包含四個部分:初始化,條件,語句,自增。值得一提的是,表示自增的時候,咱們一般用i++來代i=i+1這種比較複雜的寫法。
在不少狀況下,使用while循環是一個比較麻煩的選擇,所以咱們有了第二種更方便的循環語句:for循環。for循環的語句格式以下:
for(初始化;條件;自增){ 語句 }
和while循環同樣,for循環也包含這四個部分,只不過格式上更爲簡便。上面的代碼能夠改成:
for(var i = 0; i < 5;i ++){ alert(i); }
那麼,回到咱們的getElementsByTagName方法上來。經過循環的方式,咱們能夠很輕鬆的將代碼進行簡化:
var aDiv = getElementsByTagName('div'); for(i = 0;i < 4;i ++){ //i->0,1,2,3 aDiv[i].style.background='red'; }
這裏還存在最後一個小問題,若是個人div個數發生了改變(例如郵箱,每一個人郵箱裏面的郵件個數都是不一樣的),而我在函數用i<4將div塊的個數定爲4個,那麼會產生HTML和JS代碼不一致的狀況,每次執行都須要修改JS。實際上,這個例子裏的div個數,就是aDiv這個數組的長度,所以咱們可使用用length屬性來解決這個問題。
var aDiv = getElementsByTagName('div'); for(i = 0;i < aDiv.length;i ++){ //i->0,1,2,3 aDiv[i].style.background='red'; }
這樣不管html代碼如何修改div塊的個數JS也能夠自動適應了。
全選、反選、不選是網頁常常會用到的功能,它們分別是怎麼實現的呢?
咱們給網頁添加button和多個checkbox,但願經過button來控制checkbox的選中狀況。根據咱們前面所學的知識,咱們應該採起以下思路:經過getElementById選中button,而後給button添加onclick事件,而後經過getElementsByTagName選中input標籤來操做checkbox。這裏有一個小小的問題,由於checkbox和button屬性的標籤都是input,因此若是經過input標籤來進行元素選擇,會同時選中checkbox和button,產生一些問題。
這裏能夠採用一個小技巧解決這個問題。咱們將全部checkbox放入一個id爲div1的標籤中,而後在JS採用以下寫法:
var oDiv = document.getElementById('div1'); var aCh = oDiv.getElementById('input');
也就是說,getElementById前不必定是document,在本例中先選中了div1,再從div1中選中input,這樣就避免了選中button的狀況。
在HTML中,控制checkbox選中狀況的屬性爲checked,同理在JS裏,能夠經過操縱checked屬性來改變checkbox的選中狀況(選中時checked屬性爲true,未選中時爲false)。true/false在JS裏被稱爲布爾值,具體概念之後再講。
具體代碼以下:
<html> <head> <meta charset="utf-8"> <title>無標題文檔</title> <script> window.onload=function () { var oBtn1=document.getElementById('btn1'); var oBtn2=document.getElementById('btn2'); var oBtn3=document.getElementById('btn3'); var oDiv=document.getElementById('div1'); var aCh=oDiv.getElementsByTagName('input'); oBtn1.onclick=function () { for(var i=0;i<aCh.length;i++) { aCh[i].checked=true; } }; oBtn2.onclick=function () { for(var i=0;i<aCh.length;i++) { aCh[i].checked=false; } }; oBtn3.onclick=function () { for(var i=0;i<aCh.length;i++) { if(aCh[i].checked==true) { aCh[i].checked=false; } else { aCh[i].checked=true; } } }; }; </script> </head> <body> <input id="btn1" type="button" value="全選" /><br> <input id="btn2" type="button" value="不選" /><br> <input id="btn3" type="button" value="反選" /><br> <div id="div1"> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> <input type="checkbox" /><br> </div> </body> </html>