1. 节点操作
1.1 DOM节点
DOM节点
- DOM树里每一个内容都称之为节点
节点类型
元素节点
- 所有的标签 比如 body、 div
- html 是根节点 属性节点
- 所有的属性 比如 href 文本节点
- 所有的文本 其他
1.2 查找节点
父节点查找
parentNode 属性:返回最近一级的父节点 找不到返回为null
//父节点
<div>
<p></p>
<span></span>
</div>
//查找父节点
let p = document.querySelector('p');
console.log(p.parentNode);//div
console.log(p.parentNode.parentNode.parentNode);//html
关闭二维码案例: 思考:
- 关闭按钮 和 erweima 是什么关系呢?
- 父子关系 所以,我们完全可以这样做:
- 点击关闭按钮, 直接关闭它的爸爸,就无需获取erweima元素了
- 点击关闭按钮, 关闭的是二维码的盒子, 还要获取erweima盒子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.erweima {
width: 149px;
height: 152px;
border: 1px solid #000;
background: url(./images/456.png) no-repeat;
position: relative;
}
.close {
position: absolute;
right: -52px;
top: -1px;
width: 50px;
height: 50px;
background: url(./images/bgs.png) no-repeat -159px -102px;
cursor: pointer;
border: 1px solid #000;
}
</style>
</head>
<body>
<div class="erweima">
<span class="close"></span>
</div>
<div class="erweima">
<span class="close"></span>
</div>
<div class="erweima">
<span class="close"></span>
</div>
<div class="erweima">
<span class="close"></span>
</div>
<div class="erweima">
<span class="close"></span>
</div>
<script>
let cl = document.querySelectorAll('.close');
for(let i= 0;i<cl.length;i++){
cl[i].addEventListener('click',function(){
cl[i].parentNode.style.display = 'none';
})
}
</script>
</body>
</html>
子节点查找:
childNodes
- 获得所有子节点、包括文本节点(空格、换行)、注释节点等
console.log(div.childNodes);
//NodeList(5) [text, p, text, span, text]
children (重点)
- 仅获得所有元素节点
- 返回的还是一个伪数组
let div = document.querySelector('div');
console.log(div.children);
//[p,span]
兄弟关系查找:
下一个兄弟节点
nextElementSibling 属性
console.log(p.nextElementSibling);//span
上一个兄弟节点
previousElementSibling 属性
console.log(p.previousElementSibling);//null
1.3 增加节点
很多情况下,我们需要在页面中增加元素
- 比如,点击发布按钮,可以新增一条信息
一般情况下,我们新增节点,按照如下操作:
- 创建一个新的节点
- 把创建的新的节点放入到指定的元素内部
创建节点
即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
创建元素的三种方式
<script>
// 三种创建元素方式区别
// 1. document.write() 创建元素 如果页面文档流加载完毕,再调用这句话会导致页面重绘
var btn = document.querySelector('button');
btn.onclick = function() {
document.write('<div>123</div>');
}
// 2. innerHTML 创建元素
var inner = document.querySelector('.inner');
for (var i = 0; i <= 100; i++) {
inner.innerHTML += '<a href="#">百度</a>'
}
var arr = [];
for (var i = 0; i <= 100; i++) {
arr.push('<a href="#">百度</a>');
}
inner.innerHTML = arr.join('');
// 3. document.createElement() 创建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 100; i++) {
var a = document.createElement('a');
create.appendChild(a);
}
</script>
追加节点
要想在界面看到,还得插入到某个父元素中
插入到父元素的最后一个子元素:
插入到父元素中某个子元素的前面
学成在线案例渲染
需求:按照数据渲染页面
分析:
①:准备好空的ul 结构
②:根据数据的个数,创建一个新的空li
③:li里面添加内容 img 标题等
④:追加给ul
克隆节点
特殊情况下,我们新增节点,按照如下操作:
- 复制一个原有的节点
- 把复制的节点放入到指定的元素内部
cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
- 若为true,则代表克隆时会包含后代节点一起克隆
- 若为false,则代表克隆时不包含后代节点
- 默认为false
删除节点
node.removeChild() 方法从 node节点中删除一个子节点,返回删除的节点。
<button>删除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
</ul>
<script>
// 1.获取元素
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
// 2. 删除元素 node.removeChild(child)
// ul.removeChild(ul.children[0]);
// 3. 点击按钮依次删除里面的孩子
// btn.onclick = function() {
// if (ul.children.length == 0) {
// this.disabled = true;
// } else {
// ul.removeChild(ul.children[0]);
// }
// }
btn.addEventListener('click',function(){
if (ul.children.length == 0) {
this.disabled = true;
} else {
ul.removeChild(ul.children[0]);
}
})
</script>
案例:删除留言
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
</ul>
<script>
// 1. 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2. 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
// console.log(text.value);
// (1) 创建元素
var li = document.createElement('li');
// 先有li 才能赋值
li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
// (2) 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
// (3) 删除元素 删除的是当前链接的li 它的父亲
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
// 删除的是 li 当前a所在的li this.parentNode;
ul.removeChild(this.parentNode);
}
}
}
}
</script>
DOM的核心总结
关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
创建
增
删
改
查
属性操作
2.时间对象
2.1 实例化
在代码中发现了 new 关键字时,一般将这个操作称为实例化
- 创建一个时间对象并获取时间
获得当前时间
let date = new Date();
console.log(date);
获得指定时间
let date = new Date('2021-12-7');
console.log(date);
2.2 时间对象方法
时间对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式
页面显示时间
需求:将当前时间以:YYYY-MM-DD HH:mm 形式显示在页面
案例
分析:
①:调用时间对象方法进行转换
②:字符串拼接后,通过 innerText 给 标签
<body>
<div></div>
<script>
let div = document.querySelector('div');
let date = new Date();
// let year = date.getFullYear();
// let mon = date.getMonth();
// let day = date.getDate();
// console.log(date.getFullYear()+ '-' + date.getMonth()+ '-' +date.getDate() );
// div.innerHTML = year + '-' + mon + '-' + day;
div.innerHTML = date.getFullYear()+ '-' + date.getMonth()+ '-' +date.getDate();
</script>
</body>
2.3 时间戳
什么是时间戳
指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
三种方式获取时间戳
- 使用 getTime() 方法
let date = new Date();
console.log(date.getTime());
- 简写 +new Date()
console.log(+new Date());
- 使用 Date().now()
console.log(Date.now());
- 无需实例化
- 但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳 毕业倒计时效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.countdown {
width: 240px;
height: 305px;
text-align: center;
line-height: 1;
color: #fff;
background-color: brown;
/* background-size: 240px; */
/* float: left; */
overflow: hidden;
}
.countdown .next {
font-size: 16px;
margin: 25px 0 14px;
}
.countdown .title {
font-size: 33px;
}
.countdown .tips {
margin-top: 80px;
font-size: 23px;
}
.countdown small {
font-size: 17px;
}
.countdown .clock {
width: 142px;
margin: 18px auto 0;
overflow: hidden;
}
.countdown .clock span,
.countdown .clock i {
display: block;
text-align: center;
line-height: 34px;
font-size: 23px;
float: left;
}
.countdown .clock span {
width: 34px;
height: 34px;
border-radius: 2px;
background-color: #303430;
}
.countdown .clock i {
width: 20px;
font-style: normal;
}
</style>
</head>
<body>
<div class="countdown">
<p class="next">今天是2021年8月28日</p>
<p class="title">下班倒计时</p>
<p class="clock">
<span id="hour">01</span>
<i>:</i>
<span id="minutes">25</span>
<i>:</i>
<span id="scond">20</span>
</p>
<p class="tips">现在是18:30:00</p>
</div>
<script>
let t = setInterval(timer, 1000);
function timer() {
let news = document.querySelector('.next');
let tips = document.querySelector('.tips');
let hour = document.querySelector('#hour');
let minutes = document.querySelector('#minutes');
let scond = document.querySelector('#scond');
let newTimer = new Date();
news.innerHTML = `今天是${
newTimer.getFullYear() +
'年' +
(newTimer.getMonth() + 1) +
'月' +
newTimer.getDate() +
'日'
}`;
tips.innerHTML = `现在是${
newTimer.getHours() +
'時' +
newTimer.getMinutes() +
'分' +
newTimer.getSeconds() +
'秒'
}`;
let overTimer = new Date('2021-12-5 18:30:00');
let timeDifference = overTimer.getTime() - newTimer.getTime();
// console.log(timeDifference);
let h = parseInt(timeDifference / 1000 / 60 / 60/24);
let m = parseInt((timeDifference / 1000 / 60) % 60);
let s = parseInt((timeDifference / 1000) % 60);
h = h < 10 ? '0' + h : h;
m = m < 10 ? '0' + m : m;
s = s < 10 ? '0' + s : s;
hour.innerHTML = h;
minutes.innerHTML = m;
scond.innerHTML = s;
if (timeDifference <= 0) {
clearInterval(t);
hour.innerHTML = '00';
minutes.innerHTML = '00';
scond.innerHTML = '00';
}
}
timer();
</script>
</body>
</html>
3. 重绘和回流
1. 浏览器是如何进行界面渲染的
- 解析(Parser)HTML,生成DOM树(DOM Tree)
- 同时解析(Parser) CSS,生成样式规则 (Style Rules)
- 根据DOM树和样式规则,生成渲染树(Render Tree)
- 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
- 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制
- Display: 展示在页面上
2. 重绘和回流(重排)
回流(重排)
当渲染树(Render Tree)中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为回流。
重绘
由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘。
重绘不一定引起回流,而回流一定会引起重绘。
会导致回流(重排)的操作:
- 页面的首次刷新
- 浏览器的窗口大小发生改变
- 元素的大小或位置发生改变
- 改变字体的大小
- 内容的变化(如:input框的输入,图片的大小)
- 激活css伪类 (如::hover)
- 脚本操作DOM(添加或者删除可见的DOM元素)
简单理解影响到布局了,就会有回流