WebAPI编程(节点操作,时间对象,重绘和回流)

446 阅读5分钟

1. 节点操作

1.1 DOM节点

DOM节点

  • DOM树里每一个内容都称之为节点

image.png

节点类型

元素节点

  • 所有的标签 比如 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 增加节点

很多情况下,我们需要在页面中增加元素

  • 比如,点击发布按钮,可以新增一条信息

一般情况下,我们新增节点,按照如下操作:

  • 创建一个新的节点
  • 把创建的新的节点放入到指定的元素内部

创建节点

即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点

创建元素的三种方式

image.png

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

追加节点

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

插入到父元素的最后一个子元素:

image.png 插入到父元素中某个子元素的前面

image.png

学成在线案例渲染

image.png 需求:按照数据渲染页面

分析:

①:准备好空的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>

案例:删除留言

image.png

    <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的核心总结

image.png 关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。

创建

image.png

image.png

image.png

image.png

image.png

属性操作

image.png

2.时间对象

2.1 实例化

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

  • 创建一个时间对象并获取时间

获得当前时间

    let date = new Date();
    console.log(date);

获得指定时间

    let date = new Date('2021-12-7');
    console.log(date);

2.2 时间对象方法

时间对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式

image.png

image.png

页面显示时间

需求:将当前时间以: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秒起至现在的毫秒数,它是一种特殊的计量时间的方式

三种方式获取时间戳

  1. 使用 getTime() 方法
let date = new Date();
    console.log(date.getTime());
  1. 简写 +new Date()
 console.log(+new Date());
  1. 使用 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. 浏览器是如何进行界面渲染的

image.png

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

2. 重绘和回流(重排)

回流(重排)

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

重绘

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

重绘不一定引起回流,而回流一定会引起重绘。

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

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

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

今天多一份拼搏,明日多一份欢笑