0


Web前端系列技术之Web APIs基础(从基础开始)③

CSDN话题挑战赛第2期
参赛话题:学习笔记

Web APIs基础学习三

在上一章中主要学习了关于 事件监听 的处理问题,感兴趣的小伙伴可以回顾一下 Web前端系列技术之Web APIs基础(从基础开始)② 中所介绍的内容;

在学习完事件监听之后,使用事件监听处理对应的DOM对象是项目开发过程中实现用户交互必不可少的操作,例如 动态创建用户评论区 ;当然这里所要实现的功能就不仅仅是要使用到事件侦听操作了,还需要动态的创建实现评论区所用到的标签元素以及评论时间,那么这里就需要学到关于 ==DOM节点操作==以及 时间对象 的知识;

那么今天主要介绍的内容就是:
一、节点操作
二、时间对象
三、重绘与重排(回流)
四、评论区案例


文章目录


一、节点操作

基础理解: 此处所指的节点指的是 DOM节点;在之前学习到过 DOM树 ;那么结合着树的结构,可以知道在树中的每一个点位都被称为 节点 ,同样,这里的DOM树种所包含的每一个内容便都可以称之为 DOM节点,在对于这些节点的操作过程种,主要也就分为四种操作方式,

一般情况下,是用到最多的;

1. DOM节点

节点与节点之间也会有所不同,主要划分的节点类型为三类,当然也有其他的,因为项目开发的过程中并不常用,所以这里就不做过多的赘述了:

  1. 元素节点(重点): 所有的标签,比如 bodydiv等,其中html 属于根节点;
  2. 属性节点: 所有的属性 比如 href、id等
  3. 文本节点: 所有的文本
  4. 其他

在这里插入图片描述

⭐注意:元素节点是一个极其重要的节点内容,它可以更好的让我们理清标签元素之间的关系;

2. 查找节点

所谓的查找节点操作,主要是依赖于节点之间的关系实现查找,在DOM节点的关系中,被划分成了三类:父节点、子节点 和 兄弟节点,以便于查找到节点内容;

2.1 父节点查找

基础语法结构:

子元素.parentNode

⭐注意:

  1. parentNode 是属性,而非方法
  2. 返回 最近一级的父节点 找不到返回为 null

2.2 子节点查查找

在子节点查找中,主要分为两种方法;

基础语法结构:

//方法一(了解);
父元素.childNodes

//方法二(重点):
父元素.children

⭐注意:

  • childNodes 获得所有子节点、包括文本节点(空格、换行)、注释节点等;
  • children 仅获得所有元素节点,返回的还是一个伪数组(重点);

2.3. 兄弟节点查找

在兄弟节点查找中,主要分为两种情况:

基础语法结构:

//下一个兄弟节点
元素.nextElementSibling
//上一个兄弟节点
元素.previousElementSibling

⭐注意:

nextElementSibling

previousElementSibling

都属于属性;

3. 增加节点

在项目的开发的过程中,很多功能都需要实现标签的动态添加,例如,评论区功能 ;不过,在实现增加节点的过程中,往往分为两步开发:
① 创建一个新的节点;
② 把创建的新的节点放入到指定的元素内部;

3.1 创建节点

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

基础语法结构:

//属于一个方法
document.createElement('标签名')

⭐注意:这里需要写的是标签名,因为要创建的是标签

3.2 追加节点

基础概念: 如果需要在界面有所呈现,那就需要将创建好的标签插入到某个父元素中,这里又分为两种情况:

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

父元素.appendChild(要插入的元素)

② 插入到父元素中某个子元素的前面:

父元素.insertBefore(要插入的元素, 在哪个元素的前面)

⭐注意:此处该如何定义元素的位置呢?利用父查子生成的伪数组查询下标的方式插入;

父元素.children[i]

3.3 克隆节点

特殊情况下,新增节点也可以通过克隆的方式进行添加,主要操作如下:

  1. 复制一个原有的节点
  2. 把复制的节点放入到指定的元素内部

基础语法结构:

//克隆一个已有的元素节点
元素.cloneNode(布尔值)

⭐注意:

cloneNode

会克隆出一个跟原标签一样的元素,括号内传入布尔值:

  • 若为true,则代表克隆时会包含后代节点一起克隆
  • 若为false,则代表克隆时不包含后代节点
  • 默认为false

4. 删除节点

若一个节点在页面中已不需要时,可以删除它,在JavaScript 原生DOM操作 中,要删除元素必须通过父元素删除;

基础语法结构:

父元素.removeChild(要删除的元素)

⭐注意:

  1. 如不存在父子关系则删除不成功;
  2. 删除节点隐藏节点display:none) 有区别的: 隐藏节点还是存在的,但是删除,则从html中删除节点;

二、时间对象

基础概念: 用来表示时间的对象,通常用来得到当前系统时间;但是在创建时间对象的时候,需要进行 实例化

基本语法结构:

//获取当前时间let date =newDate()//获取指定时间let date =newDate(2022-09-17)

效果如下:
在这里插入图片描述

⭐注意:在创建时间对象的时候,需要用到

new

关键字来进行实例化操作,这里涉及到了构造函数的用法,后期会详细介绍的

1. 时间对象方法

由于时间对象所返回的数据并不能直接被使用,所以需要转换为实际开发中常用的格式,具体如表所示:
方法作用说明getFullYear()获得年份获取四位年份getMonth()获得月份取值为 0 ~ 11getDate()获取月份中的每一天不同月份取值也不相同getDay()获取星期取值为 0 ~ 6getHours()获取小时取值为 0 ~ 23getMinutes()获取分钟取值为 0 ~ 59getSeconds()获取秒取值为 0 ~ 59
代码样例如下:

//获取元素let div = document.querySelector('div')// 防止留白getime()//获取当前时间functiongetime(){let dt =newDate()let year = dt.getFullYear()let month = dt.getMonth()let date = dt.getDate()let hours = dt.getHours()let minute = dt.getMinutes()let second = dt.getSeconds()let arr =['星期日','星期一','星期二','星期三','星期四','星期五','星期六']let day = dt.getDay()//补零
      hours<10?hours+='0':hours
      minute<10?minute+='0':minute
      second<10?second+='0':second
      // 设置内容
      div.innerHTML =`现在的北京时间${year}年${month}月${date}日${hours}点${minute}分${second}秒 &nbsp;&nbsp;&nbsp;${arr[day]}`}// 定时器setInterval(getime,1000)

具体效果:
在这里插入图片描述

⭐注意: 当然,在项目开发的过程中,显示时间的功能还是有很多需要注意的地方:

  1. 在获取月份的过程中,由于 getMonth() 的取值范围为 0~11 ,所以在开发的过程中,需要将该函数方法进行优化 => getMonth()+1
  2. 页面所要呈现的时间是动态跳动的,所要需要将获取的时间对象写进定时器中,并设定每隔1s自动刷新一次
  3. 在调用定时器的时候,页面调用的第一秒会产生留白,那么主要原因的就是定时器延迟了一秒才开始运行,那么最好的解决方法就是根据程序的执行顺序,先去调用一次时间函数,再紧接着使用定时器

2. 时间戳

什么是时间戳?是指 1970年01月01日00时00分00秒起现在总毫秒数 ,它是一种特殊的计量时间的方式;

时间戳的作用:常用于编写倒计时功能;

获取时间戳的三种方式:

  1. 使用 getTime() 方法
//1. 实例化let date =newDate()//2. 获取时间戳
console.log(date.getTime())
  1. 简写 +new Date()(更常用)
console.log(+newDate())
  1. 使用 Date.now()
console.log(Date.now())

⭐注意:

  • +new Date()的使用方法中,前面的加号相当于一个 正号,用来转换成数字型的
  • Date.now()的使用方法中,无需实例化,但是只能得到当前的时间戳, 而前面两种是可以返回指定时间的时间戳

3. 时间转换公式(拓展)

因为通过时间戳得到是总毫秒数,所以要想呈现出正常的时间格式,就需要先转换为秒再计算;

  • 总秒数 = 总毫秒数 / 1000

时间转换:

  • 计算天数:d = parseInt(总秒数/ 60/60 /24);
  • 计算小时:h = parseInt(总秒数/ 60/60 %24);
  • 计算分数:m = parseInt(总秒数 /60 %60 );
  • 计算当前秒数:s = parseInt(总秒数%60);

三、重绘与重排(回流)

在了解 重绘和重排(回流) 之前,需要先了解浏览器是如何进行界面渲染的,如下图所示:

在这里插入图片描述

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

1. 重绘

由于节点(元素)的 样式改变不影响 它在文档流中的 位置文档布局 时(比如:

color

background-color

outline

等), 称为 重绘

2. 重排(回流)

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

⭐注意:

  1. outline不会撑大盒子,所以设置outline是会导致重绘的;
  2. 重绘不一定引起回流,而回流一定会引起重绘

3. 场景举例

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

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

简单理解:影响到布局了,就会有重排(回流)


四、评论区案例

具体代码:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><metahttp-equiv="X-UA-Compatible"content="ie=edge"/><title>微博发布</title><style>*{margin: 0;padding: 0;}ul{list-style: none;}.w{width: 900px;margin: 0 auto;}.controls textarea{width: 878px;height: 100px;resize: none;border-radius: 10px;outline: none;padding-left: 20px;padding-top: 10px;font-size: 18px;}.controls{overflow: hidden;}.controls div{float: right;}.controls div span{color: #666;}.controls div .useCount{color: red;}.controls div button{width: 100px;outline: none;border: none;background:rgb(0, 132, 255);height: 30px;cursor: pointer;color: #fff;font: bold 14px '宋体';transition: all 0.5s;}.controls div button:hover{background:rgb(0, 225, 255);}.controls div button:disabled{background:rgba(0, 225, 255, 0.5);}.contentList{margin-top: 50px;}.contentList li{padding: 20px 0;border-bottom: 1px dashed #ccc;position: relative;}.contentList li .info{position: relative;}.contentList li .info span{position: absolute;top: 15px;left: 100px;font: bold 16px '宋体';}.contentList li .info p{position: absolute;top: 40px;left: 100px;color: #aaa;font-size: 12px;}.contentList img{width: 80px;border-radius: 50%;}.contentList li .content{padding-left: 100px;color: #666;word-break: break-all;}.contentList li .the_del{position: absolute;right: 0;top: 0;font-size: 28px;cursor: pointer;}</style></head><body><divclass="w"><divclass="controls"><imgsrc="./images/9.6/tip.png"alt=""/><br/><!-- maxlength 可以用来限制表单输入的内容长度 --><textareaplaceholder="说点什么吧..."id="area"cols="30"rows="10"maxlength="200"></textarea><div><spanclass="useCount"id="useCount">0</span><span>/</span><span>200</span><buttonid="send">发布</button></div></div><!-- 内容列表 --><divclass="contentList"><ulid="list"></ul></div></div><script>// 模拟数据let dataArr =[{uname:'司马懿',imgSrc:'./images/9.5/01.jpg'},{uname:'女娲',imgSrc:'./images/9.5/02.jpg'},{uname:'百里守约',imgSrc:'./images/9.5/03.jpg'},{uname:'亚瑟',imgSrc:'./images/9.5/04.jpg'},{uname:'虞姬',imgSrc:'./images/9.5/05.jpg'},{uname:'张良',imgSrc:'./images/9.5/06.jpg'},{uname:'安其拉',imgSrc:'./images/9.5/07.jpg'},{uname:'李白',imgSrc:'./images/9.5/08.jpg'},{uname:'阿珂',imgSrc:'./images/9.5/09.jpg'},{uname:'墨子',imgSrc:'./images/9.5/10.jpg'},{uname:'鲁班',imgSrc:'./images/9.5/11.jpg'},{uname:'嬴政',imgSrc:'./images/9.5/12.jpg'},{uname:'孙膑',imgSrc:'./images/9.5/13.jpg'},{uname:'周瑜',imgSrc:'./images/9.5/14.jpg'},{uname:'老夫子',imgSrc:'./images/9.5/15.jpg'},{uname:'狄仁杰',imgSrc:'./images/9.5/16.jpg'},{uname:'扁鹊',imgSrc:'./images/9.5/17.jpg'},{uname:'马可波罗',imgSrc:'./images/9.5/18.jpg'},{uname:'露娜',imgSrc:'./images/9.5/19.jpg'},{uname:'孙悟空',imgSrc:'./images/9.5/20.jpg'},{uname:'黄忠',imgSrc:'./images/9.5/21.jpg'},{uname:'百里玄策',imgSrc:'./images/9.5/22.jpg'},]// 需求1:检测用户输入字数//   1. 注册input事件//   2. 将文本的内容的长度赋值给对应的数值//   3. 表单的maxlength属性可以直接限制在200个数之间let textarea = document.querySelector('textarea')let useCount = document.querySelector('.useCount')// 发布按钮let send = document.querySelector('#send')let ul = document.querySelector('#list')
    textarea.addEventListener('input',function(){
      useCount.innerHTML =this.value.length
    })// 需求2: 输入不能为空//   点击button之后判断//   判断如果内容为空,则提示不能输入为空, 并且直接return 不能为空//   防止输入无意义空格, 使用字符串.trim()去掉首尾空格//   并将表单的value值设置为空字符串//   同时下面红色为设置为0
    send.addEventListener('click',function(){if(textarea.value.trim()===''){
        textarea.value =''
        useCount.innerHTML =0returnalert('内容不能为空')}// 随机数functiongetRandom(min, max){return Math.floor(Math.random()*(max - min +1))+ min
      }let random =getRandom(0, dataArr.length -1)// 需求3:   新增留言  写到send 的里面// 创建一个小li,然后里面通过innerHTML追加数据let li = document.createElement('li')// 随机获取数据数组里面的内容, 替换newNode的图片和名字以及留言内容//img图片中,动态添加链接的时候,就不要写/>中的/了,因为会改变图片地址
      li.innerHTML =`
       <div class="info">
      <img class="userpic" src=${dataArr[random].imgSrc}>
      <span class="username">${dataArr[random].uname}</span>
      <p class="send-time"> ${newDate().toLocaleString()} </p>
      </div>
      <div class="content">${textarea.value}</div>
      <span class="the_del">X</span>`// 需求4:删除留言  放到追加的前面// 在事件处理函数里面获取点击按钮, 注册点击事件// 必须在事件里面获取, 外面获取不到// 删除对应的元素(通过this获取对应的那条需要删除的元素)// 放到追加进ul的前面,这样创建元素的同时顺便绑定了事件,方便后续删除留言// 使用 li.querySelector()let del = li.querySelector('.the_del')
      del.addEventListener('click',function(){// 删除操作  点击的是X  删除的小li  父元素.removeChild(子元素)
        ul.removeChild(li)})// 利用时间对象将时间动态化new Date().toLocaleString()// 追加给 ul  用  父元素.insertBefore(子元素, 那个元素的前面)
      ul.insertBefore(li, ul.children[0])// 需求5:重置// 将表单域内容重置为空// 将userCount里面的内容重置为0
      textarea.value =''
      useCount.innerHTML =0})</script></body></html>

具体效果:

在这里插入图片描述


总结

今天是继续学习Web APIs的第三天,内容不多,但练习极为重要,今天所总结出来的所有知识,希望对大家有用,同时也希望这篇文章可以有一个好的展现量和得到更多人的支持,谢谢每一位浏览文章的人,要相信小柴码文,必是好文,欢迎各位 点赞+收藏+关注 啦! ! !


以上就是所要介绍的Web APIs基础学习的第三节内容,后续即将更新前端开发的学习目标。感谢关注和支持,让我们一起成长!

有兴趣可回顾一下JavaScript基础学习的文章内容,再结合之前所介绍的CSS基础学习以及HTML基础学习,大脑里的内容会更加丰富而充实的,毕竟综合性复习和学习是更会加深印象的哟!!!


本文转载自: https://blog.csdn.net/IAMLSD550/article/details/126903740
版权归原作者 小柴爱程序 所有, 如有侵权,请联系我们删除。

“Web前端系列技术之Web APIs基础(从基础开始)③”的评论:

还没有评论