节点操作
DOM节点
介绍:
在网页中所有对象和内容都被称为节点,如文档、元素、文本、属性、注释等。节点(Node)是 DOM 最基本的单元,并派生出不同类型的节点,它们共同构成了文档的树形结构模型。
根据 DOM 规范,整个文档是一个文档节点,每个标签是一个元素节点,元素包含的文本是文本节点,元素的属性是一个属性节点,注释属于注释节点,以此类推。
节点类型:
- 元素节点(重点),所有标签,html是根节点;
- 属性节点,例如:href属性;
- 文本节点:所有的文本;
- 其他。
作用:
有助于我们理清标签元素间的关系;再就是让我们在js中选择对象更方便。
DOM树:
查找节点
1、父节点查找:
语法:
子元素.parentNode
例如:
<body>
<div>
我是父元素
<span>我是子元素</span>
</div>
<script>
// 选择dom元素span
let span = document.querySelector('span')
// 查找并输出span父元素,‘log’输出父元素标签
console.log(span.parentNode)
// 查找并输出span父元素,‘dir’输出父元素对象
console.dir(span.parentNode)
</script>
</body>
效果:
注意:
如果子元素上面没有父元素,则返回null。
2、子节点查找
语法:
1、父元素.childNodes----获得所有子节点、包括文本节点(空格、换行)、注释节点等。
2、父元素.children----仅获得标签元素节点(常用),返回的还是一个伪数组。
<body>
<div>
<span>大儿子</span>
<span>中儿子</span>
<span>小儿子</span>
</div>
<script>
// 选择dom元素div
let div = document.querySelector('div')
// 查找并输出div父元素下的所有子节点
console.log(div.childNodes)
// 查找并输出div父元素下的子元素标签
console.log(div.children)
</script>
</body>
效果:
注意:
子节点查找的结果,返回值都为一个伪数组;
如果没有子元素,则返回空数组。
3、兄弟节点查找
语法:
1、上一个兄弟节点
dom元素.previousElementSibling
2、下一个兄弟节点
dom元素.nextElementSibling
例如:
<body>
<div>我是大</div>
<div class="zhong">我是中</div>
<div>我是小</div>
<script>
// 选择dom元素div
let div = document.querySelector('.zhong')
// 查找并输出'中div元素'的上一个兄弟节点
console.log(div.previousElementSibling)//log输出标签
// 查找并输出'中div元素'的下一个兄弟节点
console.log(div.nextElementSibling)//log输出标签
</script>
</body>
效果:
注意:
如果没有查找到兄弟元素,则返回null。
增加节点
介绍:
我们可以在js里创建新的节点,就像在html结构中添加新的标签一样,我们只需要把新建的节点插进页面内部,就可以在页面中正常显示,效果完全和在html结构中添加新的标签一样。
我们既可以创建标签节点也可以创建文本节点等等。
创建节点
1、创建标签节点
语法:document.createElement('标签名')----这一整体就为一个标签
如:
<script>
// 新建一个div标签节点,并用输出显示,‘log’输出
console.log(document.createElement('div'))
// 新建一个div标签节点,并用输出显示,‘dir’输出
console.dir(document.createElement('div'))
</script>
效果:
2、创建文本节点:
语法:document.createTextNode('文本')----这一整体为一个文本
如:
<script>
// 新建一个文本节点,并用输出显示,‘log’输出
console.log(document.createTextNode('我是文本'))
// 新建一个文本节点,并用输出显示,‘dir’输出
console.dir(document.createTextNode('我是文本'))
</script>
效果:
注意:
创建的节点还不能直接在页面中看到,还需要插入到页面中。
追加节点(插入节点)
介绍:
要想在界面看到,还得插入到某个父元素中。
1、插入为父元素的最后一个子元素
语法:
父元素.appendChild(要插入的dom元素)
例如:
<body>
<div>
<span>儿子1</span>
<span>儿子2</span>
</div>
<script>
let div = document.querySelector('div')
// 新建一个标签节点
let span = document.createElement('span')
// 把标签节点插入到父元素的最后面
div.appendChild(span)
// 输出父标签
console.log(div)
</script>
</body>
效果:
前
注意:
- appendChild(元素) 如果该元素是已经存在网页中, appendChild作用类似 移动;
- appendChild(元素) 如果该元素新创建的, appendChild作用类似 简单的插入。
2、插入到指定子元素前面
语法:
父元素.insertBefore(要插入的元素,在哪个元素前面)
例如:
<body>
<div>
<span>儿子1</span>
<span class="span2">儿子2</span>
</div>
<script>
let div = document.querySelector('div')
// 选择到第二个子元素
let span2 = document.querySelector('.span2')
// 新建一个标签节点
let span = document.createElement('span')
// 把标签节点插入到父元素的第二个子元素前面
div.insertBefore(span, span2)
// 输出父标签
console.log(div)
</script>
</body>
效果:
注意:
1、和appendChild一样,如果要插入的元素 是已经存在的,那么insertBefore作用移动;如果要插入的元素是新创建的,insertBefore作用,仅仅插入。
2、如果没有想好把新节点插入到哪个子元素上面,传递一个null(默认插入到父容器最后面成为最后一个子元素);"在哪个元素前面"写为"dom父元素.children[0]"则表示插入为第一个子元素。
克隆节点
介绍:
复制一个原有的节点。
语法:
元素.cloneNode(布尔值);
- 布尔值默认为false,意思是只复制元素本身;
- 布尔值为true,意思是也把元素的子节点一块复制。
例如:
<body>
<div>
我是父节点
</div>
<script>
let div = document.querySelector('div')
// 只复制元素本身
console.log(div.cloneNode(false))
// 复制元素的本身和所有子节点
console.log(div.cloneNode(true))
</script>
</body>
效果:
注意:
元素克隆了还要插入到页面中才能在页面中显示。
删除节点
介绍:
若一个节点在页面中已不需要时,可以删除它;在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除。
1、删除子元素
语法:
父元素.removeChild(要删除的元素)
如:
<body>
<div>
<span>儿子1</span>
<span class="span2">儿子2</span>
</div>
<script>
let div = document.querySelector('div')
let span2 = document.querySelector('.span2')
// 删除儿子2
div.removeChild(span2)
// 输出div
console.log(div)
</script>
</body>
效果:
注意:
如不存在父子关系则删除不成功。
删除节点和隐藏节点(display:none) 有区别的: 隐藏节点还是存在的,但是删除,则从html中删除节点。
2、删除本身
语法:
元素.remove()
如:
<body>
<div>
<span>儿子1</span>
<span class="span2">儿子2</span>
</div>
<script>
let div = document.querySelector('div')
let span2 = document.querySelector('.span2')
// 删除本身
span2.remove()
// 输出父元素
console.log(div)
</script>
</body>
效果:
时间对象
介绍:
用来表示时间的对象;
作用:
可以得到当前系统时间。
语法:
new Date( )---整体表示为时间对象;
括号里可以填写时间,如果填写了,则表示,这个时间对象为指定时间对象,如let date=new Date('1949-10-01')-----获得指定时间;如果没有填写,则表示获得现在的系统时间。
方法:
例如:
<script>
//获取时间对象
let date = new Date()
// 获取年份
let a = date.getFullYear()
// 获取月份
let b = date.getMonth()
// 获取月份中的每一天
let c = date.getDate()
// 获取星期
let d = date.getDay()
// 获取小时
let e = date.getHours()
// 获取分钟
let f = date.getMinutes()
// 获取秒
let g = date.getSeconds()
console.log(`${a}年${b}月${c}日--星期${d}--${e}时${f}分${g}秒`)
</script>
效果:
时间戳
介绍:
是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式。
获取时间戳的三种方式
1、时间对象.getTime( )
<script>
console.log(new Date().getTime())//1650102943203
</script>
<script>
// 获得指定时间到现在的时间戳
console.log(new Date(2000, 10, 17, 08, 00, 00).getTime())//974419200000
</script>
2、+new Date( )
<script>
console.log(+new Date( ))//1650103009757
</script>
<script>
// 获得指定时间到现在的时间戳
console.log(+new Date(2000, 10, 17, 08, 00, 00))//974419200000
</script>
3、Date.now( )
<script>
console.log(Date.now())//1650103037013
</script>
注意:
- 无需实例化;
- 但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳
拓展
在代码中发现了 new 关键字时,一般将这个操作称为实例化。
重绘和回流
问:浏览器是如何进行界面渲染的?
答:
- 解析(Parser)HTML,生成DOM树(DOM Tree);
- 同时解析(Parser) CSS,生成样式规则 (Style Rules);
- 根据DOM树和样式规则,生成渲染树(Render Tree);
- 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小);
- 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制;
- Display: 展示在页面上。
回流(重排)
介绍:
当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为 回流。
原因:
简单理解影响到布局了,就会有回流。
会导致回流(重排)的操作:
- 页面的首次刷新;
- 浏览器的窗口大小发生改变;
- 元素的大小或位置发生改变;
- 改变字体的大小;
- 内容的变化(如:input框的输入,图片的大小);
- 激活css伪类 (如::hover);
- 脚本操作DOM(添加或者删除可见的DOM元素)。
影响:
损耗比较多浏览器性能。
重绘
介绍:
由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘。
会导致重绘的操作:
主要修改了外观颜色字体颜色等等。
影响:
性能损坏比较低。
注意:
- 重绘不一定引起回流,而回流一定会引起重绘;
- 尽量不要出现回流。