节点操作+时间对象+时间戳+重绘和回流

205 阅读6分钟

节点操作

DOM节点

介绍:

在网页中所有对象和内容都被称为节点,如文档、元素、文本、属性、注释等。节点(Node)是 DOM 最基本的单元,并派生出不同类型的节点,它们共同构成了文档的树形结构模型。

根据 DOM 规范,整个文档是一个文档节点,每个标签是一个元素节点,元素包含的文本是文本节点,元素的属性是一个属性节点,注释属于注释节点,以此类推。

节点类型:

  1. 元素节点(重点),所有标签,html是根节点;
  2. 属性节点,例如:href属性;
  3. 文本节点:所有的文本;
  4. 其他。

作用:

有助于我们理清标签元素间的关系;再就是让我们在js中选择对象更方便。

DOM树:

image-20220416151622033

查找节点

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>

效果:image-20220416155204819

注意:

如果子元素上面没有父元素,则返回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>

效果:image-20220416160628385

注意:

子节点查找的结果,返回值都为一个伪数组;

如果没有子元素,则返回空数组。

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>

效果:image-20220416161708980

注意:

如果没有查找到兄弟元素,则返回null。

增加节点

介绍:

我们可以在js里创建新的节点,就像在html结构中添加新的标签一样,我们只需要把新建的节点插进页面内部,就可以在页面中正常显示,效果完全和在html结构中添加新的标签一样。

我们既可以创建标签节点也可以创建文本节点等等。

创建节点

1、创建标签节点

语法:document.createElement('标签名')----这一整体就为一个标签

如:

   <script>

        // 新建一个div标签节点,并用输出显示,‘log’输出
        console.log(document.createElement('div'))

        // 新建一个div标签节点,并用输出显示,‘dir’输出
        console.dir(document.createElement('div'))
    </script>

效果:image-20220416163033405

2、创建文本节点:

语法:document.createTextNode('文本')----这一整体为一个文本

如:

<script>

        // 新建一个文本节点,并用输出显示,‘log’输出
        console.log(document.createTextNode('我是文本'))

        // 新建一个文本节点,并用输出显示,‘dir’输出
        console.dir(document.createTextNode('我是文本'))
    </script>

效果:image-20220416163324430

注意:

创建的节点还不能直接在页面中看到,还需要插入到页面中。

追加节点(插入节点)

介绍:

要想在界面看到,还得插入到某个父元素中。

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>

效果:

image-20220416164836155

注意:
  1. appendChild(元素) 如果该元素是已经存在网页中, appendChild作用类似 移动;
  2. 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>

效果:image-20220416165425795

注意:

1、和appendChild一样,如果要插入的元素 是已经存在的,那么insertBefore作用移动;如果要插入的元素是新创建的,insertBefore作用,仅仅插入。

2、如果没有想好把新节点插入到哪个子元素上面,传递一个null(默认插入到父容器最后面成为最后一个子元素);"在哪个元素前面"写为"dom父元素.children[0]"则表示插入为第一个子元素。

克隆节点

介绍:

复制一个原有的节点。

语法:

元素.cloneNode(布尔值);

  1. 布尔值默认为false,意思是只复制元素本身;
  2. 布尔值为true,意思是也把元素的子节点一块复制。

例如:

<body>
    <div>
        我是父节点
    </div>

    <script>

        let div = document.querySelector('div')

        // 只复制元素本身
        console.log(div.cloneNode(false))
        // 复制元素的本身和所有子节点
        console.log(div.cloneNode(true))
    </script>
</body>

效果:image-20220416171545834

注意:

元素克隆了还要插入到页面中才能在页面中显示。

删除节点

介绍:

若一个节点在页面中已不需要时,可以删除它;在 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>

效果:image-20220416172826806

注意:

如不存在父子关系则删除不成功。

删除节点和隐藏节点(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>

效果:image-20220416173131871

时间对象

介绍:

用来表示时间的对象;

作用:

可以得到当前系统时间。

语法:

new Date( )---整体表示为时间对象;

括号里可以填写时间,如果填写了,则表示,这个时间对象为指定时间对象,如let date=new Date('1949-10-01')-----获得指定时间;如果没有填写,则表示获得现在的系统时间。

方法:

image-20220416174345110

例如:

  <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>

效果:image-20220416175042939

时间戳

介绍:

是指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>
注意:
  1. 无需实例化;
  2. 但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳

拓展

在代码中发现了 new 关键字时,一般将这个操作称为实例化。

重绘和回流

问:浏览器是如何进行界面渲染的?

答:

  1. 解析(Parser)HTML,生成DOM树(DOM Tree);
  2. 同时解析(Parser) CSS,生成样式规则 (Style Rules);
  3. 根据DOM树和样式规则,生成渲染树(Render Tree);
  4. 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小);
  5. 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制;
  6. Display: 展示在页面上。

回流(重排)

介绍:

当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为 回流。

原因:

简单理解影响到布局了,就会有回流。

会导致回流(重排)的操作:

  1. 页面的首次刷新;
  2. 浏览器的窗口大小发生改变;
  3. 元素的大小或位置发生改变;
  4. 改变字体的大小;
  5. 内容的变化(如:input框的输入,图片的大小);
  6. 激活css伪类 (如::hover);
  7. 脚本操作DOM(添加或者删除可见的DOM元素)。

影响:

损耗比较多浏览器性能。

重绘

介绍:

由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘。

会导致重绘的操作:

主要修改了外观颜色字体颜色等等。

影响:

性能损坏比较低。

注意:

  1. 重绘不一定引起回流,而回流一定会引起重绘;
  2. 尽量不要出现回流。