JS获取盒模型属性值的特点:
1.获取的都是数字不带单位
2.获取的都是整数,不会出现小数
3.获取的结果都是复合样式值(好几个元素的样式组合在一起的值),如果只想获取单一样式值(例如:只想获取padding),我们的盒子模型就操作不了
获取元素具体的某个样式值:
1.【元素】.style.xxx操作获取
只能获取行内
2. 获取当前元素所有经过浏览器计算过的样式(只要浏览器渲染它)
不管当前样式写在哪,不管是否写了
标准浏览器(IE9+)
window.getComputedStyle([元素], [伪类, 一般都写null])获取到当前元素所有被浏览器计算过的样式(后面有px)
IE6-8 window.currentStyle
三大系列:client、offset、scroll
1.client
- clientWidth & clientHeight:获取当前元素可视区域的宽高(内容的宽高+左右/上下padding)
和内容是否溢出无关(和是否设置overflow:hidden无关)- clientTop & clientLeft :获取(上/左)边框的宽度
需求:获取当前页面一屏幕的宽度和高度
document.documentElement.clientWidth || document.body.clientWidth
document.documentElement.clientHeight || document.body.clientHeight
2.offset:
- offsetWidth & offsetHeight :在client的基础上加上border(和内容是否溢出没有关系)
- offsetParent:当前盒子的父级参照物
- offsetTop / offsetLeft: 获取当前盒子距离其父级参照物的偏移量(上偏移/左偏移),当前盒子的内边框到父元素外边框
注意: 同一个平面中,元素的父级参照物和结构没有必然联系,默认他们的父级参照都是body,body的父级参照物为null
参照物可以改变,构建出不同的平面即可,所以改变元素的定位(position:relative/absolute/fixed)可以改变父级参照物
需求:不管何种定位,获取当前元素距离body的偏移量(左偏移和上偏移)
1.首先获取当前元素的左偏移
2.在这个基础上累加:
A:父参照物的边框
B:父参照物的偏移
let offset = function (curEle){
//1.先获取当前元素本身的左/上偏移
let curLeft = curEle.offsetLeft,
curTop = curEle.offsetTop,
p = curEle.offsetParent;
//2.累加父参照物的边框和偏移
while(p.tagName !== 'BODY){
curLeft += p.clientLeft;
curLeft += p.offsetLeft;
curTop += p.clientTop;
curTop += p.offsetTop;
p = p.offsetParent;
}
return {
top: curTop,
left: curLeft
}
}
3.scroll
- scrollWidth & scrollHeight :真实内容的宽高,如果溢出算上paddingTop加真实内容的高度
需求获取当前页面的真实宽高,包括溢出
document.documentElement.scrollWidth || document.body.scrollWidth
document.documentElement.scrollHeight || document.body.scrollHeight- (可读写)scrollTop / scrollLeft :滚动条卷去的宽度或者高度
最大卷去高度;document.documentElement.scrollHeight - document.documentElement.clientHeight
操作浏览器的盒子模型属性,我们一般都要写两套,用来兼容各种模式下的浏览器
回到顶部:document.documentElement.scrollTop = 0
let winHandle = function (attr, value) {
if(typeof value != undefined){
document.documentElement[attr] = value;
document.body[attr] = value;
return;
}
return document.documentElement[attr] || document.body[attr];
}
封装样式操作
let getCss = function(curEle, attr) {
if(typeof window.getComputedStyle === 'undefined'){
return;
}
let val = =window.getComputedStyle(curEle, null)[attr],
reg = /^-?\d+(\.\d+)?(px|rem|em|pt)?$/i;
reg.test(val) ? val = parseFloat(val) : null;
return val;
}
//JS给元素设置样式:1.添加类名;2.通过行内样式设置
/*
* 细节处理:
* 1.如果要考虑IE6-8,透明度这个样式 在低版本浏览器中不是使用opacity,而是filter(两套都要设置)
* 2.如果传递进来的value值没有带单位,我们根据情况设置px单位
* ->某些样式属性才会加width、height、padding、margin、font-size、top、left、bottom、right
* ->用户自己传递的value值是没有单位的
*/
let setCss = function (curEle, attr, value) {
if (attr === 'opacity'){
curEle.style.opacity = value;
curEle.style.filter = `alpha(opacity=${value*100})`;
return;
}
//下为纯数字的情况
if(!isNaN(value)){
let reg = /^(width|height|fontSize|(margin|padding)?(top|left|right|bottom)?))$/i
reg.test(attr) ? value += 'px' : null;
return;
}
curEle['style'][attr] = value;
return;
}
//给元素批量设置样式
//遍历传进来的options,有多少键值对,就循环多少次
let setGroupCss = function (curEle, options={}){
for(let attr in options){
if(!options.hasOwnProperty(attr))break;
setCss(curEle, attr, options[attr]);
}
}
//css:集合GET/SET/SET-GROUP为一体
let css = function(...arg) {
// => ARG: 传递的实参集合
let len = arg.length,
second = arg[1],
fn = getCss;
len >= 3 ? fn = setCss : null;
len === 2 && (second instanceof Object) ? fn = setGroupCss : null;
return fn(...arg);
}
补充:
for in循环只遍历当前对象可枚举的属性
1.对象的私有属性是可枚举的
2.自己在类的原型上设置的属性也是可枚举的,for-in循环也会被遍历出来
3.浏览器内置的属性一般是不可枚举的