JS盒子模型常用屬性
CSS如下:
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#box{
margin: 100px;
padding: 30px;
width: 200px;
height: 200px;
border: 30px solid royalblue;
}
</style>
HTML如下:
<body>
<div id="box" class="test00 test01 test02 test03" name="aaa" index="0">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut corporis facere libero nulla numquam possimus provident quae quisquam. Accusantium commodi culpa dolores esse excepturi maxime praesentium recusandae sapiente sit voluptates.
</div>
</body>
小技巧:自動(dòng)生成隨機(jī)文本
使用方法:在div元素中書寫lorem或lorem + 單詞數(shù)量 (不加單詞數(shù)量則生成默認(rèn)長段隨機(jī)文本)
使用這個(gè)功能可以幫助我們生成隨機(jī)文本,不必費(fèi)力的去找填充文本。
Lorem ipsum,中文又稱“亂數(shù)假文”, 是指一篇常用于排版設(shè)計(jì)領(lǐng)域的拉丁文文章 [1] ,主要的目的為測(cè)試文章或文字在不同字型、版型下看起來的效果。
Lorem ipsum從西元15世紀(jì)開始就被廣泛地使用在西方的印刷、設(shè)計(jì)領(lǐng)域中,在電腦排版盛行之后,這段被傳統(tǒng)印刷產(chǎn)業(yè)使用幾百年的無意義文字又再度流行。由于這段文字以“Lorem ipsum”起頭,并且常被用于標(biāo)題的測(cè)試中,所以一般稱為Lorem ipsum,簡稱為Lipsum。 ---參考百度百科
1、JS盒子模型指的是通過JS中提供的一系列屬性和方法,獲取頁面中元素的樣式信息值
<script>
var box = document.getElementById('box');
console.dir(box);
</script>

div#box(這個(gè)元素有很多自己的私有屬性)通過這個(gè)元素所屬的類的原型找到原型鏈上公共的屬性和方法。
原型鏈如下:
div#box => HTMLDivElement.prototype => HTMLElement.prototype => Element.prototype =>Node.prototype => EvenTarget.prototype => Object.prototype
1) Element.attributes
Element.attributes 屬性返回該元素所有屬性節(jié)點(diǎn)的一個(gè)實(shí)時(shí)集合。該集合是一個(gè) NamedNodeMap 對(duì)象,不是一個(gè)數(shù)組,所以它沒有 數(shù)組 的方法,其包含的 屬性 節(jié)點(diǎn)的索引順序隨瀏覽器不同而不同。更確切地說,attributes 是字符串形式的名/值對(duì),每一對(duì)名/值對(duì)對(duì)應(yīng)一個(gè)屬性節(jié)點(diǎn)。

NamedNodeMap
NamedNodeMap 接口表示屬性節(jié)點(diǎn) Attr 對(duì)象的集合。盡管在 NamedNodeMap 里面的對(duì)象可以像數(shù)組一樣通過索引來訪問,但是它和 NodeList 不一樣,對(duì)象的順序沒有指定。
NamedNodeMap 對(duì)象是即時(shí)的(live),因此,如果它內(nèi)部包含的對(duì)象發(fā)生改變的話,該對(duì)象會(huì)自動(dòng)更新到最新的狀態(tài)。

也就是說attributes屬性除了擁有自己的屬性,還繼承了它內(nèi)置類NameNodeMap上的方法。
走一個(gè)測(cè)試下這些方法
- NamedNodeMap.getNamedItem(屬性名) 通過屬性名獲取屬性節(jié)點(diǎn)(Attr)。
box.attributes.getNamedItem('name')
//=> name='aaa'
- NamedNodeMap.item() 通過索引獲取屬性節(jié)點(diǎn)(Attr),或者,當(dāng)索引超出或等于屬性節(jié)點(diǎn)的數(shù)量時(shí),返回 null。
box.attributes.item(0)
//=> id='box'
- NamedNodeMap.removeNamedItem(屬性名) 移除一個(gè)屬性節(jié)點(diǎn)(Attr)。
box.attributes.removeNamedItem('id') //名為id的屬性節(jié)點(diǎn)被刪除
- NamedNodeMap.setNamedItem(node) 替換或添加一個(gè)屬性節(jié)點(diǎn)(Attr)到映射(map)中。
如果此節(jié)點(diǎn)已存在,則將替換該節(jié)點(diǎn),并返回被替換的節(jié)點(diǎn),否則返回值是 null。
//創(chuàng)建屬性節(jié)點(diǎn)
var typ = document.createAttribute('id');
//添加屬性值
typ.nodeValue = 'box';
//添加屬性節(jié)點(diǎn)到元素上
box.attributes.setNamedItem(typ);
2) classList 和className

classList 和className的區(qū)別
Element.classList 是一個(gè)只讀屬性,返回一個(gè)元素的類屬性的實(shí)時(shí)DOMTokenList 集合。
使用 classList 是替代element.className作為空格分隔的字符串訪問元素的類列表的一種方便的方法。
className 獲取或設(shè)置指定元素的class屬性的值。
- 設(shè)置新的class屬性值會(huì)把原先的覆蓋掉
let cName = elementNodeReference.className;
elementNodeReference.className = cName;
- cName是一個(gè)字符串變量,表示當(dāng)前元素的class屬性的值,可以是由空格分隔的多個(gè)class屬性值.
Element.classList 的方法
add( String [, String] )
添加指定的類值。如果這些類已經(jīng)存在于元素的屬性中,那么它們將被忽略。
box.classList.add('test004')
remove( String [,String] )
刪除指定的類值。
box.classList.remove('test001')
client系列(當(dāng)前元素的幾個(gè)私有屬性)
clientWidth / clientHeight 內(nèi)容寬度/高度 + 左右/上下填充(也就是padding值)
內(nèi)容的寬度和高度:我們?cè)O(shè)置的width和height這兩個(gè)樣式就是內(nèi)容的寬度和高度,如果沒設(shè)置height值,容器高度會(huì)根據(jù)里面的內(nèi)容自適應(yīng),這樣獲取的值就是真實(shí)內(nèi)容的寬度和高度。
如果設(shè)置了height值,不論內(nèi)容多了還是少了,內(nèi)容的高度就是設(shè)置的height值
真實(shí)內(nèi)容的寬度和高度:代指的是內(nèi)容的實(shí)際寬高(和我們?cè)O(shè)置的width和height沒有必然的聯(lián)系)
比如:只設(shè)置容器width=200px ;height=200px,如果里面的放了10萬個(gè)字,就會(huì)內(nèi)容溢出,而height還是原來的height,等于200px;那么文字內(nèi)容就等于它溢出的高度+容器設(shè)置height值。
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#box{
margin: 100px;
padding: 30px;
width: 200px;
/*height: 200px;*/
border: 30px solid royalblue;
}
</style>
</head>
<body>
<div id="box" class=" " name="aaa" index="0">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut corporis facere libero nulla numquam possimus provident quae quisquam. Accusantium commodi culpa dolores esse excepturi maxime.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus at cupiditate delectus, eligendi excepturi explicabo, harum illum maxime minima minus quae quibusdam ratione saepe, sunt suscipit temporibus ullam vero voluptatibus.
</div>
<script>
var box = document.getElementById('box');
console.log(box.clientWidth); // = > 260
console.log(box.clientHeight); // => 480
</script>
</body>


clientLeft 和 clientTop
clientLeft:左邊框的寬度 clientTop:上邊框的高度 (就是border[left/top]Width)
3)offset系列
offsetWidth / offsetHeight
offsetWidth = clientWidth + clientLeft
*2 ( 左右邊框?qū)挾龋?br> offsetHeight = clientWidth + clientTop*2 ( 上下邊框高度)
offsetParent
當(dāng)前元素的父級(jí)參照物
offsetLfet / offsetHeight
當(dāng)前元素的外邊框距離父級(jí)參照物的內(nèi)邊框的偏移量
4)scroll系列
scrollWidth / scrollHeight
和clientWidth / clientHeight 一樣(前提是:容器中內(nèi)容沒有溢出的情況下)
如果容器中的內(nèi)容溢出,我們獲取的結(jié)果如以下規(guī)則:
scrollWidth:真實(shí)內(nèi)容的寬度(包含溢出)+ 左填充(padding-left)
scrollWidth:真實(shí)內(nèi)容的高度(包含溢出)+ 上填充(padding-top)
獲取到結(jié)果都是約等于的值
容器是否設(shè)置overflow=‘hidden’對(duì)于最終的結(jié)果是有影響的;在不同瀏覽器中獲取的結(jié)果也不是相同的

scrollLeft / scrollTop
表示滾動(dòng)條卷去的寬度/高度

關(guān)于JS盒子模型的取值問題
如果寬度/高度設(shè)置值帶有小數(shù)位,用這13個(gè)屬性去獲取值,不會(huì)出現(xiàn)小數(shù),都會(huì)四舍五入取整

關(guān)于操作瀏覽器本身的盒子模型信息
document.documentElement.clientWidth / document.documentElement.clientHeight
是當(dāng)前瀏覽器可視窗口的寬度和高度(一屏幕的寬度和高度)
document.documentElement.scrollWidth / document.documentElement.scrollWidth
是當(dāng)前頁面的真實(shí)寬度和高度【所有屏加起來(也就是頁面很長出現(xiàn)了滾動(dòng)條)的寬度和高度,是一個(gè)約等于值】
操作瀏覽器盒子模型的方法
兼容性比較好的寫法
document.documentElement[attr] || document.body[attr];
document.documentElement[attr] 必須寫在前面,[attr]表示要獲取或設(shè)置的屬性
例如:獲取滾動(dòng)條卷去頁面的高度scrollHeight
document.documentElement.scrollHeight || document.body.scrollHeight;
//如果只傳遞了attr沒有傳value,默認(rèn)“獲取”
//如果兩個(gè)參數(shù)都傳遞了,則為“設(shè)置”
代碼如下:
function win(attr,value) {
if (typeof value === 'undefined'){
return document.documentElement[attr] || document.body[attr]; // [attr]表示屬性名
}
document.documentElement[attr] = value;
document.body[attr] = value;
}
獲取元素的某一個(gè)具體的樣式的屬性值需要注意事情
1、元素.style.屬性名
這中方式需要把元素的樣式都寫在行內(nèi)樣式上才可以(寫在樣式中是不管用的)
2、使用window.getComputedStyle()
Window.getComputedStyle()方法返回一個(gè)對(duì)象,該對(duì)象在應(yīng)用活動(dòng)樣式表并解析這些值可能包含的任何基本計(jì)算后報(bào)告元素的所有CSS屬性的值。 私有的CSS屬性值可以通過對(duì)象提供的API或通過簡單地使用CSS屬性名稱進(jìn)行索引來訪問。
可以簡單理解為,獲取所有經(jīng)過瀏覽器計(jì)算過的樣式集合
語法
let style = window.getComputedStyle(element, [pseudoElt]);
比如:window.getComputedStyle(el,null).color
參數(shù)element
用于獲取計(jì)算樣式的
Element
參數(shù)pseudoElt
指定一個(gè)要匹配的偽元素的字符串。必須對(duì)普通元素省略(或null)。null 的意思是不返回偽類元素
返回的style是一個(gè)實(shí)時(shí)的CSSStyleDeclaration對(duì)象,當(dāng)元素的樣式更改時(shí),它會(huì)自動(dòng)更新本身。
CSSStyleDeclaration 表示一個(gè)CSS屬性鍵值對(duì)的集合。CSSStyleDeclaration也是由window.getComputedStyle()返回的只讀接口
瀏覽器兼容性
在IE6~8 下不兼容,因?yàn)閣indow下沒有
getComputedStyle這個(gè)屬性,可以使用currentStyle來獲取
語法:ele.currentStyle.attr
官方的提醒:該特性是非標(biāo)準(zhǔn)的,請(qǐng)盡量不要在生產(chǎn)環(huán)境中使用它!
【方法使用】使用window.getComputedStyle()獲取偽元素屬性的值
HTML如下:
<div class="box">
<p id="boxp">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam animi, at aut consequatur doloribus expedita facere hic libero pariatur, quae quibusdam tempora temporibus totam unde voluptatum! Amet debitis eius tenetur?
</p>
</div>
CSS如下:
*{
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 14px;
}
.box{
margin:20px auto;
width:300px;
padding: 20px;
border: 1px dashed #cccccc;
}
.box p{
line-height: 1.5;
}
/*:before :after ->在一個(gè)元素標(biāo)簽的前面或者后面,創(chuàng)建一個(gè)新的虛擬標(biāo)簽
可以給這個(gè)虛擬的標(biāo)簽增加樣式和內(nèi)容。
*/
.box p:before{
display: block;
height: 30px;
line-height: 30px;
text-align: center;
content: 'lorem';
background: royalblue;
color: #ffffff;
}
.box p:after{
display: block;
height: 30px;
line-height: 30px;
text-align: center;
content: 'lorem';
background: royalblue;
color: #ffffff;
}
JS如下:
var boxp = document.getElementById('boxp');
window.getComputedStyle(boxp, 'after').content = 'hello 123' ; //=> Uncaught DOMException: Failed to set the 'content' property on 'CSSStyleDeclaration'
//報(bào)錯(cuò):CSSStyleDeclaration是一個(gè)CSS屬性鍵值對(duì)的集合,只讀接口不允許修改CSS屬性的值
console.log(window.getComputedStyle(boxp, 'after').content); // => "lorem"
【方法使用】 獲取當(dāng)前元素所有經(jīng)過瀏覽器計(jì)算過的樣式中的[attr]對(duì)應(yīng)的值
1、使用try、catch來處理兼容
前提:必須保證try中的代碼塊在不兼容瀏覽器中執(zhí)行的時(shí)候報(bào)錯(cuò),才可以用catch捕獲到異常信息,進(jìn)行其它處理,不管是什么瀏覽器,都需要先執(zhí)行try中的代碼塊(消耗性能)
function getCss(curEle, attr) {
var val = null;
try {
val = window.getComputedStyle(curEle,null)[attr];
}catch(e){
val = curEle.currentStyle[attr];
}
return val;
}
2、判斷當(dāng)前瀏覽器中是否存在這個(gè)屬性或者方法
function getCss(curEle, attr) {
var val = null;
if ('getComputedStyle' in window) {
val = window.getComputedStyle(curEle,null)[attr];
}else {
val = curEle.currentStyle[attr];
}
return val;
}
3、獲取到當(dāng)前的瀏覽器是IE6~8
function getCss(curEle, attr) {
var val = null;
if (/MSIE (6|7|8)/.test(navigator.userAgent)) {
val = curEle.currentStyle[attr];
}else {
val = window.getComputedStyle(curEle,null)[attr];
}
return val;
}
改進(jìn)1.0:把獲取的樣式值單位去掉
function getCss(curEle, attr) {
var val = null;
if ('getComputedStyle' in window) {
val = window.getComputedStyle(curEle,null)[attr];
}else {
val = curEle.currentStyle[attr];
}
return parseFloat(val); //return parseFloat(val) 對(duì)于某些樣式屬性的值是不能去掉單位的,例如:float、position、margin、padding、border這些復(fù)合值、background...
}
function getCss(curEle, attr) {
var val = null, reg = null;
if ('getComputedStyle' in window) {
val = window.getComputedStyle(curEle, null)[attr];
} else {
val = curEle.currentStyle[attr];
}
reg = /^(-?\d+(\.\d+)?)(px|pt|rem|em)$/;
return reg.test(val) ? parseFloat(val) : val;
}
改進(jìn)2.0:解決某些樣式屬性在不同瀏覽器中不兼容問題,比如:opacity
function getCss(curEle, attr) {
var val = null, reg = null;
if ('getComputedStyle' in window) {
val = window.getComputedStyle(curEle, null)[attr];
} else {
if (attr === 'opacity') {
val = curEle.currentStyle['filter'];
reg = /^alpha\(opacity=(\d+(?:\.\d+)?)\)$/i;
val = reg.test(val)?reg.exec(val)[1]/100:1;
}else {
val = curEle.currentStyle[attr];
}
}
reg = /^(-?\d+(\.\d+)?)(px|pt|rem|em)$/;
return reg.test(val) ? parseFloat(val) : val;
}