前端筆記之JavaScript(八)關於元素&計算後的樣式

mufengsm發表於2019-03-26

一、獲取元素方法(JS選擇器)

1.1概述

得到id元素的方法

 document.getElementById()

得到一個元素。事實上,還有一個方法可以得到標籤元素,並且得到的是多個元素:

 document.getElementsByTagName();

 

全線瀏覽器相容的,得到元素的方法,就這兩個:

document.getElementById()        通過id得到元素

document.getElementsByTagName();    通過標籤名得到元素們

 

還有更多的得到元素的方法:

document.getElementsByClassName();通過類名得到元素

document.querySelector();    通過選擇器得到元素

document.querySelectorAll();通過選擇器得到元素,得到的是一組元素

document.getElementsByName(name) nama屬性名獲取元素

這些不是全線瀏覽器相容,IE8以上開始相容。


 

1.2 getElementsByTagName

getElementsByTagName就是通過標籤名得到元素,得到的是頁面上所有的該標籤元素,得到的是陣列。陣列有下標,下標0開始,最後一項length-1。通過標籤名獲得所有標籤名這個標籤。類似於css中的標籤選擇器。選擇的是一組元素。

get        得到

elements  元素們

By        通過

TagName  標籤名字

 

var ops = document.getElementsByTagName("p");
console.log(ops);
// ops.style.backgroundColor = "skyblue"; //錯誤寫法,因為得到的是一根陣列,必須用下標獲取元素
ops[0].style.backgroundColor = "skyblue";//獲取下標為1的標籤
ops[1].style.backgroundColor = "skyblue";//獲取下標為2的標籤
ops[2].style.backgroundColor = "skyblue";//獲取下標為3的標籤
ops[3].style.backgroundColor = "skyblue";//獲取下標為4的標籤
ops[4].style.backgroundColor = "skyblue";//獲取下標為5的標籤
ops[ops.length-1].style.backgroundColor = "skyblue";//獲取最後的標籤

 

既然是陣列,就可以通過迴圈語句批量控制。

var ops = document.getElementsByTagName("p");
//迴圈給所有p標籤
for(var i = 0;i < ops.length;i++){
    console.log(i)
    ops[i].style.backgroundColor = "skyblue";
}

 

HTML標籤從上到下執行,依次是0,1,2,3,4

<div>
    <div>
        <p>0</p>
        <div>
            <p>1</p>
        </div>
        <p>2</p>
    </div>
    <p>3</p>
</div>
<p>4</p>
//頁面上只有一個p標籤,也必須用陣列[]得到
document.getElementsByTagName('p')[2].style.color = "red";

 


1.3連續打點呼叫get

先去選擇一個HTML標籤,然後選擇這個HTML標籤中所有的p元素

連續打點呼叫get方法,控制範圍,選中父親下的什麼什麼元素。

 document.getElementsByTagName('div')[0].getElementsByTagName('p')[1].style.color = "red";

 

錯誤寫法:不要多寫document,只要開頭有一個就可以了。

 document.getElementsByTagName('div')[0].document.getElementsByTagName('p')[1].style.color = "red";

 

實際應用:先用id名去縮小範圍,內部的多選擇使用標籤選擇器。

 document.getElementById('box').getElementsByTagName('p')[1].getElementsByTagName('span')[1].style.color = 'red';

 

表格隔行變色:

var tr = document.getElementById("table").getElementsByTagName('tr');
//不管個數是多少,編號從0開始
for(var i = 0;i < tr.length;i += 2){
   //從0開始,每次加2,所以都是偶數
   tr[i].style.backgroundColor = "pink";
}
for(var i = 1;i < tr.length;i += 2){
   //從1開始,每次加2,所以都是奇數
   tr[i].style.backgroundColor = "skyblue";
}

 


1.4批量新增事件新增

如果一些相同的元素,新增相同事件,事件函式內部的程式碼幾乎相同,可以批量選擇元素新增事件。

注意:找出陣列中每一項,定義事件函式,用for迴圈中的變數。閉包可能會程式造成影響。

 

迴圈給所有p標籤新增事件,並且彈出對應的編號:

var ops = document.getElementsByTagName('p');
for(var i = 0;i < ops.length;i++){
    ops[i].onclick = function(){
        alert(i); //迴圈結束後都還執行函式,所以值
    }
}

 

但是,對編號的影響,閉包的影響又出現了。

所以每個盒子點選後都是5,而不是0,1,2,3,4

閉包的影響:匿名函式定義時,都已經記住了自己認識i,但是認識i不是表示把i的值複製一份儲存,所以匿名函式執行時(就是事件觸發時),i的值變為迴圈結束的值了。

 

解決方法1:使用IIFE關住當時定義時的作用域,點選事件發生時,執行對應的事件函式,事件函式會去找自己定義時的作用域。定義時a已經被傳遞了引數,值就已經儲存起來了。

var ops = document.getElementsByTagName('p');
for(var i = 0;i < ops.length;i++){
    (function(a){
        ops[a].onclick = function(){
            alert(a); 
        }
    })(i); //把每次迴圈i的值傳遞給函式區域性變數a
}

 

解決方法2:獲取的元素,本身封裝了大量的屬性和方法,還能自定義一些新屬性並賦值,自定義屬性後可以打點呼叫。

任何物件都可以自定義屬性,並賦值:

Math.aaa = 9999;
window.aaa = 8888;
Array.bbb = 12345;
console.log(Math.aaa)
console.log(window.aaa)
console.log(Array.bbb)
var ops = document.getElementsByTagName('p');
for(var i = 0;i < ops.length;i++){
    ops[i].index = i; //自定義屬性,並且把迴圈i的值賦值儲存到屬性中,名稱自定義的
    ops[i].onclick = function(){
        alert(this.index); //this關鍵字就代表事件源本身
    }
}

解決方式:每個元素物件新增一個自定義屬性,用屬性儲存迴圈變數,在事件函式內部與都有一個特殊關鍵字,叫thisthis會指向事件源本身,它能完全替代事件觸發的那個事件源物件。

事件源:誰觸發事件,誰就是事件源(誰就是this


 

1.5對應和排他思想

保留自己排除別人。

實際運用到程式碼中,批量控制給所有人新增一個相同樣式,然後再給被操作的元素新增特殊樣式。

做到了先排除所有人,然後再保留自己的特殊樣式。

 

對應模型:點選第一排p,第二排對用編號的p變色。

// 方法1:編號,迴圈新增事件監聽,給第一排所有p並且繫結點選事件
for(var i = 0;i < box1.length;i++){
   box1[i].index = i;
   box1[i].onclick = function(){
       console.log(this.index)
       box2[this.index].style.backgroundColor = "red";
   }
}
//方法2:IIFE
for(var i = 0;i < box1.length;i++){
   (function(i){
       // console.log(i)
       box1[i].onclick = function(){
           box2[i].style.backgroundColor = "red";
       }
   })(i);
}

 

排他思想:點選p的時候,就自己變紅色,其他所有o都變灰色

var aps = document.getElementById('box').getElementsByTagName("p");
var biaoti = document.getElementById("biaoti");
//迴圈新增監聽
for(var i = 0;i < aps.length;i++){
    aps[i].index = i; //自定義編號
    aps[i].onclick = function(){
        //每點選一個p並且,實際上兩件事
        //第一件事:讓所有人(包括自己)都變灰色
        for(var j = 0;j < aps.length;j++){
            //aps[j].style.backgroundColor = "#ccc";
            aps[j].className = ""; //清空型別
        }
        //第二件事:讓自己都變紅色
        //this.style.backgroundColor = "#f40";
        this.className = "current"; //新增類名
    }
}

 

輪播圖:

var imgList = document.getElementById('imgList').getElementsByTagName('li');
var navList = document.getElementById('navList').getElementsByTagName('li');
var leftBtn = document.getElementById('btn1');
var rightBtn = document.getElementById('btn2');
var index = 0; //全域性訊號量,是ul的li下標,下標為幾,就顯示第幾個li
//右按鈕
rightBtn.onclick = function(){
   index++;//訊號量自加
   //後驗收
   if(index > imgList.length-1){
       index = 0; //回到第一張
   }
   slide();//呼叫函式
}
//左按鈕
leftBtn.onclick = function(){
   index--;//訊號量自減
   //後驗收
   if(index < 0){
       index = imgList.length-1; //回到第一張
   }
   slide();//呼叫函式
}
//封裝函式
function slide(){
   //排他:將所有人的隱藏(類名清空),再讓自己加current類名(誰有類名誰就顯示)
   for(var i = 0;i < imgList.length; i++){
       //第一步:讓所有圖片li標籤隱藏
       imgList[i].className = "";
       //讓所有ol的li都清空
       navList[i].className = "";
   }
   //讓自己顯示,其他li隱藏
   //給當前編號的ul的li新增類名,顯示圖片
   imgList[index].className = "current";
   //給當前編號的ol的li新增類名,顯示小圓點
   navList[index].className = "current";
}
//下面小圓點如果點選,應該讓index對應的發生變化
for(var i = 0;i < navList.length;i++){
   navList[i].index = i; //自定義屬性
   navList[i].onclick = function(){
       index = this.index; //把當前被點選的li編號重新賦值給全域性變數(修改全域性)
       // index得到後,執行函式
       slide(); //呼叫函式
   }
}

 

選項卡:

var tab_li = document.getElementById('tab-hd').getElementsByTagName("li");
var tab_ul = document.getElementById('tab-bd').getElementsByTagName("ul");
//批量給li新增滑鼠移入事件
for(var i = 0; i < tab_li.length;i++){
   tab_li[i].index = i; //自定義屬性,儲存i的值
   tab_li[i].onmouseenter = function(){
       //排他思想:
       //第一步:先清空所有li元素的類名
       for(var j = 0; j < tab_li.length;j++){
           tab_li[j].className = ""; //清空li的類名
           tab_ul[j].className = ""; //清空ul的類名
       }
       //第二步再給自己新增類名
       this.className = "current"; //給當前滑鼠移入的li新增類名
       tab_ul[this.index].className = "current"; //給對應編號的ul新增類名
   }
}

 


二、得到計算後的樣式

2.1高階瀏覽器和低階瀏覽器的不同寫法

現在我們只能得到行內的樣式,事實上DOM提供了可靠的API,得到計算後的樣式(內嵌式和外鏈式)。

W3C制定的標準API,所有現代瀏覽器(包括IE9,但不包括之前的版本)支援window.getComputedStyle()方法,該方法接收一個要進行樣式計算的元素,並返回一個樣式物件樣式物件提供了getPropertyValue()的方法,用於檢索特定CSS樣式屬性的計算樣式。getPropertyValue()方法接收css屬性名稱,而不是駝峰式的名稱。getPropertyValue()可以不寫,直接用[]方括號來代替檢索屬性也可以。

 

get得到,computed計算後,style樣式

get得到,property屬性,vaule

 

這種方式獲取和設定的都是行內樣式,無法獲取內嵌和外鏈的CSS樣式:

 console.log(oBox.style.width); 

 

 window.getComputedStyle(oBox);  //得到當前div元素所有的CSS樣式

 window.getComputedStyle(oBox).getPropertyValue("width"); //獲取計算後的樣式

 

 

所有的window物件的方法,都可以不寫window

 window.alert();

等價於:

 alert();

 

得到計算後的樣式,可以直接使用getComputedStyle()方法,不用寫window

還要注意,引號裡面是CSS屬性,不是駝峰命名法。

 getComputedStyle(oBox).getPropertyValue("padding-left")

 

getPropertyValue()方法看著就不爽,所以可以用“[]”來代替它

 getComputedStyle(oBox)["padding-left"];

 

計算後的綜合結果,就是這個元素此時的狀態:

getComputedStyle(oBox)["background"];
getComputedStyle(oBox)["background-color"]; //樣式計算後結果是得到rgb的值
getComputedStyle(oBox)["background-image"];
getComputedStyle(oBox)["border"];

上面的方法IE678一律不相容!!!

DOM提供給JS的非常牛,一個元素此時的狀態,可以完全被得到,好用的屬性,但是不相容。所以IE678不相容getComputedStyle()方法,寫另外一套寫法:附加在元素身上的currentStyle屬性,它和style點語法一樣,使用駝峰命名法。

 

IE678支援以下寫法:

注意:currentStyle得到樣式,必須用駝峰命名法,寫法和oBox.style.width這種一樣

 oBox.currentStyle.paddingLeft

可以不寫點語法,使用“[]”,但是也必須是駝峰命名。

 oBox.currentStyle['paddingLeft']

 

alert(oBox.currentStyle.width);
alert(oBox.currentStyle.height); //不寫高度得到的是auto,不能獲取被內容撐開的高度
alert(oBox.currentStyle.backgroundColor); //顏色值會原樣輸出,pink

顏色值在高階瀏覽器中是rgb(),低版本瀏覽器是原樣輸出

 

總結:
高階瀏覽器:
window.getComputedStyle(oBox).getPropertyValue("padding-left");
getComputedStyle(oBox).getPropertyValue("padding-left");
getComputedStyle(oBox)["padding-left"];

IE6/7/8瀏覽器
oBox.currentStyle.paddingLeft
oBox.currentStyle["paddingLeft"];

 


2.2相容寫法

IE678低階瀏覽器,不認識getComputedStyle視為錯誤

Chrome等高階瀏覽器,不認識currentStyle視為錯誤

所以,現在就要進行一個相容性寫法,新玩家會認為,要檢測瀏覽器版本,如果版本是IE678那麼……。

實際上,老司機都不這麼做。我們不關心你的瀏覽器版本是什麼,我只關心你瀏覽器的能力。

 

所以要進行能力檢測,可以在不同瀏覽器中得到相容性的寫法,輸出CSS屬性的值:

如果能使用這個方法,方法作為if語句的判斷條件就會返回true,不能使用就返回false

if(window.getComputedStyle){
   //條件滿足為真,說明當前瀏覽器認識getComputedStyle()方法
   alert(getComputedStyle(oBox)["background-color"]);
}else{
   //條件不滿足,說明當前瀏覽器不認識getComputedStyle()方法,認識currentStyle
   alert(oBox.currentStyle.backgroundColor);
}

 


 

封裝一個相容性的函式獲取一個元素某個CSS屬性值的方法。

API:傳入兩個引數,第一個是元素物件,第二個是CSS屬性名

返回值:是這個傳入元素物件的CSS屬性值

function getStyle(obj,property){
   if(window.getComputedStyle){
       //高階連起來,要把使用者輸入的CSS屬性中檢測一下是否為駝峰,如果是就轉為連字元寫法
       //強制把使用者輸入的大寫字母,變為小寫字母加“-”
       // paddingLeft 替換 padding-left
       // 正則替換:
       property = property.replace(/([A-Z])/g,function(match,$1){
           return "-" + $1.toLowerCase();
       })
       //返回計算後的樣式
       return getComputedStyle(obj)[property];
   }else{
       //IE只認識駝峰,要防止用輸入短橫,如果輸入短橫,要把短橫改為大寫字母
       //padding-left替換paddingLeft
       property = property.replace(/-([a-z])/g,function(match,$1){
           return $1.toUpperCase();
       })
       //返回計算後的樣式
       return obj.currentStyle[property];
   }
}
alert(getStyle(oBox,"padding-left"));
alert(getStyle(oBox,"backgroundColor"));

 


2.3關於opacity

opactiy取值0.0~1.0,而濾鏡取值0~100

儘管IE8和早期版本不支援opacity,通過style.opacity或者ele.currentStyle.opacity屬性取值時,返回的依然是opacity值,即使瀏覽器完全忽略了opatity值。這是一個好事兒,當我們能夠保證opactiyfilter中設定的屬性是一致的,則JavaScript讀取opactiy值就算是相容的。

支援opacity的瀏覽器,總會將.6這種寫法規範為0.6 。 而不支援opacity的瀏覽器則會返回原有的形式.5。這是一個小坑,進行比較的時候需要注意。

設定opacity的時候,我們需要同時設定filter屬性,filter中的數值是opacity100倍。

 

查了100

var oBox = document.getElementById("box");
// alert(oBox.style.opacity); //JS沒有相容性問題
// alert(oBox.currentStyle.opacity); //低版本沒有相容性問題
var opacity = 0.5;
oBox.style.opacity = opacity;
oBox.style.filter = "alpha(opacity="+(opacity * 100)+")";

 

相關文章