JS中的DOM操作:盒子模型属性
DOM:document object model 文档对象模型,提供系列的属性和方法,让我们能在JS中操作页面中的元素
1.获取元素的属性和方法
document.getElementById([ID])
[context].getElementsByTagName([TAG-NAME])
[context].getElementsByClassName([CLASS-NAME])
//=>在IE6~8中不兼容
document.getElementsByName([NAME])
//=>在IE浏览器中只对表单元素的NAME有作用
[context].querySelector([SELECTOR])
[context].querySelectorAll([SELECTOR])
//=>在IE6~8中不兼容
//---------------------
document
document.documentElement
document.head
document.body
childNodes 所有子节点
children 所有元素子节点
//=>IE6~8中会把注释节点当做元素节点获取到
parentNode
firstChild / firstElementChild
lastChild / lastElementChild
previousSibling / previousElementSibling
nextSibling / nextElementSibling
//=>所有带Element的,在IE6~8中不兼容
2.DOM的增删改操作
document.createElement([TAG-NAME])
document.createTextNode([TEXT CONTENT])
字符串拼接(模板字符串),基于innerHTML/innerText存放到容器中
[PARENT].appendChild([NEW-ELEMENT])
[PARENT].insertBefore([NEW-ELEMENT],[ELEMENT])
[ELEMENT].cloneNode([TRUE/FALSE])
[PARENT].removeChild([ELEMENT])
//=>设置自定义属性
[ELEMENT].xxx=xxx;
console.log([ELEMENT].xxx);
delete [ELEMENT].xxx;
[ELEMENT].setAttribute('xxx',xxx);
console.log([ELEMENT].getAttribute('xxx'));
[ELEMENT].removeAttribute('xxx');
3.获取元素样式和操作样式
//=>修改元素样式
[ELEMENT].style.xxx=xxx; //=>修改和设置它的行内样式
[ELEMENT].className=xxx; //=>设置样式类
//=>获取元素的样式
console.log([ELEMENT].style.xxx); //=>获取的是当前元素写在行内上的样式,如果有这个样式,但是没有写在行内上,则获取不到
4.JS盒子模型属性
基于一些属性和方法,让我们能够获取到当前元素的样式信息,例如:clientWidth 、offsetWidth等
- client
- width / height
- top / left
- offset
- width / height
- top / left
- parent
- scroll
- width / height
- top / left
方法:window.getComputedStyle([ELEMENT],[伪类]) / [ELEMENT].currentStyle
【案例1】:盒子居中
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JS盒子模型属性</title>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.box {
box-sizing: border-box;
padding: 15px;
width: 300px;
height: 300px;
border: 10px solid lightblue;
background: lightcyan;
font-size: 18px;
line-height: 30px;
}
/* 居中:定位(五种) */
/* .box {
position: absolute;
top: 50%;
left: 50%;
margin-left: -150px;
margin-top: -150px;
} */
/* .box {
position: absolute;
top: 50%;
left: 50%;
/!* 基于CSS3变形属性中的位移,在不知道宽高的情况下也能实现效果 *!/
transform: translate(-50%, -50%);
} */
/* .box {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
} */
/* FLEX :http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html*/
/* body {
display: flex;
/!* 设置元素在FLEX容器主轴和交叉轴方向上的对齐方式:CENTER居中对齐 *!/
justify-content: center;
align-items: center;
} */
</style>
</head>
<body>
<div id="box" class="box">
夫君子之行,静以修身,俭以养德,非淡泊无以明志,非宁静无以致远。夫学须静也,才须学也,非学无以广才,非志无以成学。淫漫则不能励精,险躁则不能冶性,年与时驰,意与日去,遂成枯落,多不接世,悲守穷庐,将复何及~~
</div>
<script>
// JS实现居中:(一屏幕的宽度-盒子的宽度)/2 === LEFT
let winW = document.documentElement.clientWidth,
winH = document.documentElement.clientHeight,
box = document.getElementById('box');
box.style.position = 'absolute';
box.style.left = (winW - 300) / 2 + 'px';
box.style.top = (winH - 300) / 2 + 'px';
</script>
</body>
</html>
box-sizing的作用:
let box = document.getElementById('box');
//=>获取盒子可视区域的宽高(内容宽度+左右PADDING)
//1.内容溢出与否对他无影响
//2.获取的结果是没有单位的(其余的盒模型属性也是)
//3.获取的结果是整数,它会自己进行四舍五入(其余的盒模型属性也是)
box.clientWidth
box.clientHeight
//获取当前页面一屏幕(可视化)区域的宽高
let winW = document.documentElement.clientWidth || document.body.clientWidth;
let winH = document.documentElement.clientHeight || document.body.clientHeight;
//=>获取盒子左边框和上边框的大小
box.clientLeft
box.clientTop
let box = document.getElementById('box');
//=>在CLIENT的基础上加上BORDER == 盒子本身的宽高
box.offsetWidth
box.offsetHeight
//=>在没有内容溢出的情况下,获取的结果和CLIENT是一样的
//=>在有内容溢出的情况下,获取的结果约等于真实内容的宽高(上/左PADDING + 真实内容的高度/宽度)
//1.不同浏览器获取的结果不尽相同
//2.设置overflow属性值对最后的结果也会产生一定的影响
box.scrollWidth
box.scrollHeight
//获取整个页面真实的高度
document.documentElement.scrollHeight || document.body.scrollHeight
let box = document.getElementById('box');
//=>竖向滚动条卷去的高度
//=>横向滚动条卷去的宽度
//1.边界值
//min=0
//max=整个的高度scrollHeight - 一屏幕高度clientHeight
box.scrollTop
box.scrollLeft
//=>13个盒子模型属性,只有这两个是“可读写”的属性(既可以获取也可以设置对应的值),其余的都是“只读”属性(不能设置值,只能获取)
box.scrollTop=0;
【案例2】:回到顶部
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>回到顶部</title>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
height: 1000%;
/* CSS3中的背景颜色线性渐变 */
background: -webkit-linear-gradient(top left, lightblue, lightpink, lightyellow);
}
.link {
display: none;
position: fixed;
right: 30px;
bottom: 230px;
box-sizing: border-box;
width: 100px;
height: 100px;
background: lightcoral;
font-size: 16px;
color: #000;
text-decoration: none;
text-align: center;
line-height: 100px;
}
</style>
</head>
<body>
<a href="javascript:;" id="link" class="link">回到顶部</a>
<script>
let HTML = document.documentElement,
LINK = document.getElementById('link');
// 1.当浏览器滚动条滚动的时候,我们进行验证:卷去的高度超过两屏,我们让#LINK显示
function check() {
//winH:一屏幕高度 scrollT:卷去的高度
let winH = HTML.clientHeight,
scrollT = HTML.scrollTop;
LINK.style.display = scrollT >= winH * 2 ? 'block' : 'none';
}
window.onscroll = check;
// 2.点击回到顶部
LINK.onclick = function () {
/* 让按钮隐藏 */
LINK.style.display = 'none';
//先禁止滚动事件触发(因为在回到顶部的运动过程中,如果事件一直在,会计算按钮显示隐藏的样式,无法让按钮隐藏)
window.onscroll = null;
/* 实现动画 */
let step = 1000;
let timer = setInterval(() => {
//每一次获取最新的SCROLL-TOP值,在现有的基础上减去步长,让其走一步
let curT = HTML.scrollTop;
if (curT === 0) {
//边界判断:已经回到顶部后,我们清除定时器
clearInterval(timer);
//恢复滚动条滚动的监听事件
window.onscroll = check;
return;
}
curT -= step;
HTML.scrollTop = curT;
}, 17);
};
//SET-INTERVAL:设置一个定时器(TIMER代表这个定时器),每间隔INTERVAL这么久,就会把FUNCTUION执行一次...一直到手动清除定时器为止
// let timer = setInterval([FUNCTUION], [INTERVAL]);
// clearInterval(timer);
</script>
</body>
</html>
【案例3】:盒子模型
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JS盒子模型属性</title>
<style>
* {
margin: 0;
padding: 0;
}
.outer {
box-sizing: border-box;
margin: 20px auto;
width: 500px;
height: 500px;
background: lightcoral;
border: 10px solid orangered;
position: relative;
}
.box {
box-sizing: border-box;
margin: 20px auto;
padding: 15px;
width: 300px;
height: 300px;
border: 10px solid lightblue;
background: lightcyan;
font-size: 18px;
line-height: 30px;
overflow: auto;
}
</style>
</head>
<body>
<div class="outer" id="outer">
<div id="box" class="box">
夫君子之行,静以修身,俭以养德,非淡泊无以明志,非宁静无以致远。夫学须静也,才须学也,非学无以广才,非志无以成学。淫漫则不能励精,险躁则不能冶性,年与时驰,意与日去,遂成枯落,多不接世,悲守穷庐,将复何及~~
</div>
</div>
<script>
/*
* offset:获取当前元素距离BODY的左/上偏移(不论其父参照物是谁)
* @params
* curEle:current element当前要操作的元素
* @return
* [object]包含上/左偏移的信息 => {top:xxx,left:xxx}
* by zhufengpeixun on 2019/08/14
*/
function offset(curEle) {
let par = curEle.offsetParent,
l = curEle.offsetLeft,
t = curEle.offsetTop;
//存在父参照物,而且还没有找到BODY
while (par && par.tagName !== "BODY") {
//在原有偏移的基础上累加:父参照物的边框、父参照物的偏移
if (!/MSIE 8\.0/.test(navigator.userAgent)) {
//IE8中偏移值自已就算了边框了,不需要我们在加边框的值 navigator.userAgent获取当前浏览器的版本信息
l += par.clientLeft;
t += par.clientTop;
}
l += par.offsetLeft;
t += par.offsetTop;
//继续获取上级参照物
par = par.offsetParent;
}
return {
top: t,
left: l
};
}
</script>
</body>
</html>
5.getComputedStyle
获取当前元素所有经过浏览器计算过的样式
- 只要元素在页面中呈现出来,那么所有的样式都是经过浏览器计算的
- 哪怕你没有设置和见过的样式也都计算了
- 不管你写或者不写,也不轮写在哪,样式都在这,可以直接获取
在IE6~8浏览器中不兼容,需要基于currentStyle来获取
//=>第一个参数是操作的元素 第二个参数是元素的伪类:after/:before
//=>获取的结果是CSSStyleDeclaration这个类的实例(对象),包含了当前元素所有的样式信息
let styleObj = window.getComputedStyle([element],null);
//获取方式:
styleObj["backgroundColor"]
styleObj.display
//=>IE6~8
styleObj = [element].currentStyle;
6.图片延迟加载【较难】
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>图片延迟加载</title>
<style>
* {
margin: 0;
padding: 0;
}
img {
border: none;
}
img[src=""] {
display: none;
}
.imgBox {
box-sizing: border-box;
margin: 800px auto;
width: 300px;
height: 245px;
background: #CCC;
}
.imgBox img {
display: none;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<!--
图片延迟加载 “图片懒加载”
1.结构中,我们用一个盒子包裹着图片(在图片不展示的时候,可以占据着这个位置,并且设置默认的背景图或者背景颜色)
2.最开始,IMG的SRC中不设置任何的图片地址,把图片的真实地址设置给自定义属性DATA-SRC/TRUE-IMG(最开始不展示图片:可以让图片隐藏)
3.当浏览器窗口完全展示到图片位置的时候,我们再去加载真实图片,并且让其显示出来(第一屏幕中的图片一般都会延迟加载,来等待其它资源先加载完)
-->
<div class="imgBox">
<img src="" alt="" trueImg="images/IE3.jpg">
</div>
<!-- IMPORT JS -->
<script src="4.延迟加载.js"></script>
</body>
</html>
/*
* offset:获取当前元素距离BODY的左/上偏移(不论其父参照物是谁)
* @params
* curEle:current element当前要操作的元素
* @return
* [object]包含上/左偏移的信息 => {top:xxx,left:xxx}
* by zhufengpeixun on 2019/08/14
*/
function offset(curEle) {
let par = curEle.offsetParent,
l = curEle.offsetLeft,
t = curEle.offsetTop;
while (par && par.tagName !== "BODY") {
if (!/MSIE 8\.0/.test(navigator.userAgent)) {
l += par.clientLeft;
t += par.clientTop;
}
l += par.offsetLeft;
t += par.offsetTop;
par = par.offsetParent;
}
return {
top: t,
left: l
};
}
/*
* 图片完全显示出来的条件
* A:盒子底边距离BODY(页面最顶端)的距离:盒子的高度+盒子距BODY的上偏移
* B:浏览器底边距离BODY的距离:一屏幕的高度 + 卷去的高度
* A<=B:盒子就完全出现在用户的视野中
* 让图片显示
* 获取图片TRUE-IMG属性的值,赋值给SRC属性,当图片能正常加载出来后,让图片显示即可
*/
let imgBox = document.querySelector('.imgBox'),
_img = imgBox.querySelector('img');
//=>显示图片
//curImg:要显示的图片
function lazyImg(curImg) {
//给SRC赋值真实的图片地址
let trueImg = curImg.getAttribute("trueImg");
curImg.src = trueImg;
//校验图片是否能够正常加载出来:IMG.ONLOAD事件用来监听图片是否能加载
curImg.onload = function () {
curImg.style.display = 'block';
};
//=>设置自定义属性:isLoad存储当前图片已经加载过了
curImg.isLoad = true;
}
//=>监听页面滚动事件(不论基于什么方式,只要页面滚动了,则触发事件)
window.onscroll = function () {
//=>已经加载过就不要在重复加载了
if (_img.isLoad) return;
let HTML = document.documentElement,
B = HTML.clientHeight + HTML.scrollTop,
A = imgBox.offsetHeight + offset(imgBox).top; //=>当前案例中,获取距离BODY的上偏移完全可以imgBox.offsetTop,因为父参照物就是BODY
if (A <= B) {
//=>符合图片显示的条件了
lazyImg(_img);
}
};