JS操作盒子模型

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.浏览器内置的属性一般是不可枚举的

猜你喜欢

转载自blog.csdn.net/weixin_42098339/article/details/89846263
今日推荐