WebAPIs-03 (DOM节点的增删改查)

01-DOM节点:网页一切内容皆节点

1.1-DOM节点介绍

1.什么是节点:在HTML文档中,一切皆节点(HTML文档本身、标签、属性、注释内容、文本)

  • 2.什么是元素:元素在HTML中叫做标签,在JS的dom对象中称为元素(可以理解为标签的面向对象的叫法)
  • 3.HTML标签属于节点的一种,叫做元素节点
  • 4.节点三要素:
    • 节点类型:标签、属性、注释、文本
    • 节点名称:p、div、class(标签名)
    • 节点的值:one(属性的值)
  • 在JavaScript中,document这个对象大家一定很熟悉,哪怕是刚刚开始学习的新人,也会很快接触到这个对象。而document对象不仅仅是一个普通的JavaScript内置对象,它还是一个巨大API的核心对象,这个巨大的API就是DOM(Document Object Model),它将文档的内容呈现在JS面前,并赋予了JS操作文档的能力。
    • DOM树体现着HTML页面的层级结构,学习中经常提到的父元素子元素的说法也是建立在树这种数据结构的基础之上的,而DOM文档树则包含文档中所有内容。
      在这里插入图片描述

1.2-查找节点:子节点

  <script>
      /* 学习目标: 获取子节点与子元素
       1.获取子元素节点(重点): 父元素.children*/
      console.log(ul.children) //仅获得5个元素节点
    </script>

1.3-查找节点:兄弟节点

    <script>
      /* 学习目标: 获取兄弟元素
            1.获取上一个元素节点 : 元素.previousElementSibling
            2.获取下一个元素节点 : 元素.nextElementSibling
         */

      let li2 = document.querySelector('#li2')

      document.querySelector('.btn').onclick = function () {
        //兄弟元素 : 元素节点
        //1 上一个兄弟元素
        console.log(li2.previousElementSibling) //班长1
        li2.previousElementSibling.style.color = 'red'
        //2 下一个兄弟元素
        console.log(li2.nextElementSibling) //班长3
        li2.nextElementSibling.style.color = 'red'
      }
    </script>

1.4-查找节点:父节点

  <script>
      /* 学习目标: 获取父节点 
            子元素.parentNode
         */

      let li2 = document.querySelector('#li2')

      console.log(li2.parentNode) //ul
      console.log(li2.parentNode.parentNode) //body
      console.log(li2.parentNode.parentNode.parentNode) //html
      console.log(li2.parentNode.parentNode.parentNode.parentNode) //document 
      console.log(li2.parentNode.parentNode.parentNode.parentNode.parentNode) //null
    </script>

1.5-点击关闭二维码按钮

在这里插入图片描述

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title>关闭二维码</title>
    <style>
        .box {
            border: 1px solid #D9D9D9;
            margin: 100px auto;
            position: relative;
            width: 107px;
        }

        #x {
            border: 1px solid #D9D9D9;
            width: 14px;
            height: 14px;
            line-height: 14px;
            color: #D6D6D6;
            cursor: pointer;
            position: absolute;
            top: 0;
            left: -15px;
        }
    </style>
</head>

<body>

    <div class="box">
        <img src="images/taobao.jpg" alt="" />
        <span id="x">×</span>
    </div>

    <script>
        /* 思路分析:  点击x,隐藏box */

        //1.获取元素
        let x = document.querySelector('#x')
        
        //2.注册事件
        x.onclick = function(){
            //3.事件处理:隐藏box
            /* 
            this : 事件源 xx按钮
            this.parentNode : xx按钮的父盒子box
             */
            this.parentNode.style.display = 'none'
        }

    </script>

</body>

</html>

1.6-新增节点

  <body>
    <ul>
      <li>我是班长1</li>
      <li id="li2">我是班长2</li>
      <li>我是班长3</li>
      <li>我是班长4</li>
      <li>我是班长5</li>
    </ul>
    
    <script>
      /* 节点操作
      1.新增节点: document.createElement()
        (1)内存 创建空标签 : let li =  document.createElement('标签名')
        (2)设置内容   :  li.innerText = '文本'
        (3)添加到dom树 :  父元素.appendChild( 子元素 )
      2.克隆节点:
      3.删除节点:

      额外复习: dom中有三种语法可以实现新增节点
        1. document.write('')  
        2. 元素.innerHTML
        3. document.createElement()
      */
      let ul = document.querySelector('ul')

      //1. document.write('')  : 几乎不用
      // document.write('<h1>黑马程序员</h1>')

      //2. 元素.innerHTML :可以使用(不适合大量新增)
      //直接 = 赋值会覆盖原来的内容
      // document.body.innerHTML = '<a href="#">我是链接</a><h2>我是标题</h2>'

      //如果不想覆盖可以使用 连接符
      // document.body.innerHTML += '<a href="#">我是链接</a><h2>我是标题</h2>'

      //3.dom推荐 : document.createElement()
      //(1)内存中 创建空元素
      let newLi =  document.createElement('li')
      //(2)设置元素内容
      newLi.innerText = '我是新来的'
      console.log(newLi)
      //(3)添加到dom树
      ul.appendChild(newLi)
    </script>

1.7-克隆节点

在这里插入图片描述

<!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>
        .box {
            width: 300px;
            height: 100px;
            border: 1px solid pink;
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <button class="btn">点我克隆节点</button>
    <button class="btn1">点我克隆节点</button>
    <div class="box">
        <a href="我是链接"></a>
        <p>我是p标签</p>
        <ul>
            <li>我是ikun1</li>
            <li>我是ikun2</li>
        </ul>
    </div>
    <script>
        /* 克隆节点:  复制节点
                元素.cloneNode(布尔类型)
                    false: 不克隆后代元素
                    true:  克隆所有后代元素
           */
        let btn = document.querySelector('.btn')

        btn.onclick = function () {
            // 2.克隆box: 克隆box+所有后代元素
            // 元素.cloneNode(true)
            let cBox = document.querySelector('.box').cloneNode(true)
            // console.log(cBox) 控制台测试
            //3. 将克隆之后的元素添加到页面
            document.body.appendChild(cBox)
        }

        let btn1 = document.querySelector('.btn1')

        btn1.onclick = function () {
            // 克隆box: 只克隆box自己
            let cBox = document.querySelector('.box').cloneNode(false)
            // console.log(cBonx) 控制台测试
            //3. 将克隆之后的元素添加到页面
            document.body.appendChild(cBox)
        }
    </script>
</body>

</html>

1.8-删除节点

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button class="btn">点我删除节点</button>
    <ul>
        <li>我是班长1</li>
        <li id="li2">我是班长2</li>
        <li>我是班长3</li>
        <li>我是班长4</li>
        <li>我是班长5</li>
    </ul>

    <script>
        /* 节点操作
        1.新增节点: document.createElement()
            (1)内存 创建空标签 : let li =  document.createElement('标签名')
            (2)设置内容   :  li.innerText = '文本'
            (3)添加到dom树 :  父元素.appendChild( 子元素 )
        2.克隆节点:
            克隆元素自己      : 元素.cloneNode(false)
            克隆元素自己+后代  :元素.cloneNode(true)
        3.删除节点:  父元素.removeChild( 子元素 )
            * 注意点: 元素只能移除自己的子元素
        */

        document.querySelector('.btn').onclick = function(){
            //获取父元素
            let ul = document.querySelector('ul')
            //子元素
            let li2 = document.querySelector('#li2')
            //删除节点:  父元素.removeChild( 子元素 )
            ul.removeChild( li2 )
        }
    </script>
</body>
</html>

1.9-insertBefore实现上移动与下移

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button class="btn1">新增元素到最后面</button>
    <button class="btn2">新增元素到li2前面</button>
    <button class="btn3">新增元素到最前面</button>
    <button class="btn4">li2上移</button>
    <button class="btn5">li2下移</button>

    <ul>
        <li>我是班长1</li>
        <li id="li2">我是班长2</li>
        <li>我是班长3</li>
        <li>我是班长4</li>
        <li>我是班长5</li>
    </ul>

    <script>
        /* 新增元素
           1.只能新增到最后面   :    父元素.appendChild( 子元素 )
           2.新增到指定元素的前面:   父元素.insertBefore( 子元素,要新增到哪个元素前面 )
         */

        let ul = document.querySelector('ul')//父元素
        let li2 = document.querySelector('#li2')//li2

        //新增元素到最后面
        document.querySelector('.btn1').onclick = function(){
            //新创建元素
            let newLi = document.createElement('li')
            newLi.innerText = '我是新来的1'
            //新增到最后面
            ul.appendChild(newLi)
        }

        //新增元素到li2前面
        document.querySelector('.btn2').onclick = function(){
            //新创建元素
            let newLi = document.createElement('li')
            newLi.innerText = '我是新来的2'
            //新增到li2前面 
            ul.insertBefore( newLi,li2 )
        }

        //新增父元素到最前面
        document.querySelector('.btn3').onclick = function(){
            //新创建元素
            let newLi = document.createElement('li')
            newLi.innerText = '我是新来的3'
            //新增最前面 :  新增到原来的第一个元素的前面 
            ul.insertBefore( newLi, ul.children[0] )
        }

        //li2上移
        document.querySelector('.btn4').onclick = function(){
            /* 上移思路: 元素移动到它哥哥的前面 */
            //判断li2是不是第一个元素,如果是则不能移动
            if( li2.previousElementSibling ){
                ul.insertBefore( li2, li2.previousElementSibling )
            }else{
                alert('已经是第一个元素')
            }
        }

        //li2下移
        document.querySelector('.btn5').onclick = function(){
            /* 下移思路: 元素 移到弟弟的弟弟的前面
            弟弟的后面 = 弟弟的弟弟的前面
            */
            if( li2.nextElementSibling ){
                ul.insertBefore(li2, li2.nextElementSibling.nextElementSibling )
            }else{
                alert('已经是最后一个元素')
            }
        }
    </script>
</body>
</html>

02-节点操作语法总结

    <script>
        /* 查询节点
        1.查询子元素节点 :  父元素.children
        2.查询兄弟元素节点 : 
            上一个兄弟元素 :  元素.previousElementSibling
            下一个兄弟元素 :  元素.nextElementSibling
        3.查询父节点 :  元素.parentNode
        */

        /* 节点操作
        1.新增节点: document.createElement()
            (1)内存 创建空标签 : let li =  document.createElement('标签名')
            (2)设置内容   :  li.innerText = '文本'
            (3)添加到dom树 :  父元素.appendChild( 子元素 )
        2.克隆节点:
            克隆元素自己      : 元素.cloneNode(false)
            克隆元素自己+后代  :元素.cloneNode(true)
        3.删除节点:  父元素.removeChild( 子元素 )
            * 注意点: 元素只能移除自己的子元素
        */


        /* 新增节点
           1.新增到最后面     :  父元素.appendChild(子元素)
           2.新增到某个元素前面:  父元素.insertBefore(子元素,要加到哪个元素前面)
         */

    </script>

03.案例分享

1.案例:微博发布

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-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>
    <div class="w">
      <!-- 操作的界面 -->
      <div class="controls">
        <img src="./images/9.6/tip.png" alt="" /><br />
        <!-- maxlength 可以用来限制表单输入的内容长度 -->
        <textarea
          placeholder="说点什么吧..."
          id="area"
          cols="30"
          rows="10"
          maxlength="200"
        ></textarea>
        <div>
          <span class="useCount" id="useCount">0</span>
          <span>/</span>
          <span>200</span>
          <button id="send">发布</button>
        </div>
      </div>
      <!-- 微博内容列表 -->
      <div class="contentList">
        <ul id="list"></ul>
      </div>
    </div>

    <!-- 添加了hidden属性元素会直接隐藏掉 -->
    <li hidden>
      <div class="info">
        <img class="userpic" src="./images/9.6/03.jpg" />
        <span class="username">死数据:百里守约</span>
        <p class="send-time">死数据:发布于 2020120500:07:54</p>
      </div>
      <div class="content">死数据:111</div>
      <span class="the_del">X</span>
    </li>

    <script>
      // maxlength 是一个表单属性, 作用是给表单设置一个最大长度
      // 模拟数据
      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.文本域输入事件 :  获取文本域内容的长度  赋值给 span标签文本
          文本域文本 : area.value
          文本域文本长度 : area.value.length
          span标签文本: span.innerText

      2.发布按钮点击事件
        2.1 非空判断 : 判断用户有没有输入  去除字符串空格 trim()
          area.value.trim() = ''
        2.2 新增元素
          (1)创建空li元素  (2)设置li元素innerHTML  (3)添加到ul最前面
        2.3 清空表单文本 + span内容
          area.value = ''

      3.点击删除按钮, 删除按钮所在的li元素
        * 只有父元素才可以删除li元素:  ul.removeChild(li)

      本案例难点: 删除按钮无法直接注册事件
        * 原因: 删除按钮并不是一开始就有的,而是点击发布按钮之后动态生成的
        * 解决问题 : 
          * 实际开发常用: '事件委托'技术    
          * 另外思路 : 什么时候生成li元素,什么时候获取删除按钮
          
      */

      //1.获取元素
      let area = document.querySelector('#area')//文本域
      let useCount = document.querySelector('#useCount')//span
      let send = document.querySelector('#send')//发布按钮
      let list = document.querySelector('#list')//ul列表
      //2.1 文本域输入事件
      area.oninput = function(){
        //3.获取文本域内容的长度  赋值给 span标签文本
        useCount.innerText = this.value.length
      }

      //2.2 点击发布按钮
      send.onclick = function(){
        //3.1 非空判断
        if( area.value.trim() == '' ){
          alert('请输入内容')
        }else{
          //3.2 新增元素
          //(1)创建空li元素
          let li = document.createElement('li')
          //(2)设置li元素内容
          //(2.1)生成数组随机下标
          let index =  parseInt( Math.random()*dataArr.length )
          li.innerHTML = `<div class="info">
          <img class="userpic" src="${ dataArr[index].imgSrc  }" />
          <span class="username">${ dataArr[index].uname  }</span>
          <p class="send-time">发布于 ${ new Date().toLocaleString() }</p>
          </div>
          <div class="content">${ area.value }</div>
          <span class="the_del">X</span>`
          //(3)添加到ul最前面
          list.insertBefore( li , list.children[0] ) 

          /* 一定要有li,才可以获取删除按钮
          document.querySelector() : 整个页面查询元素
          父元素.querySelector()    : 父元素中查找元素
          */
          li.querySelector('.the_del').onclick = function(){
            // console.log(this)//xx按钮
            list.removeChild( this.parentNode )
          }
        }
        //4.清空表单文本 + span内容
        area.value = ''
        useCount.innerText = 0
      }
    </script>
  </body>
</html>

04.定时器

  1.定时器 : 一断代码 间隔时间 重复执行
  2.定时器语法 : 

2.1 setInterval() :

永久定时器。 一旦开启永久重复执行,只能手动清除
开启: let timeID = setInterval( function(){}, 间隔时间 )
清除: clearInterval( timeID )

2.2 setTimeout() :

一次定时器。 间隔时间只会执行一次,之后自动清除
开启: let timeID = setTimeout( function(){}, 间隔时间 )
清除: clearTimeout( timeID )

  /**
  * @description: 开启定时器
  * @param {function} 一段代码 
    * 回调函数 : 如果一个函数的参数是函数,这个参数函数叫做回调函数 
  * @param {number} 间隔时间, 单位毫秒ms    1s = 1000ms
  * @return: 定时器id
    * 一个页面可以开启很多个定时器,浏览器为了便于管理。就会给每一个定时器一个编号,称之为定时器id 
  */

01. 3秒后自动关闭广告 setTimeout() : 一次定时器

在这里插入图片描述

    <style>
      img {
        position: absolute;
        right: 0;
        bottom: 0;
      }
    </style>
  </head>

  <body>
    <img src="./images/ad.png" alt="" />

    <script>
      //开启3秒 一次定时器
      setTimeout( function(){
        document.querySelector('img').style.display = 'none'
      } , 3000 )
    </script>

02.日期对象Date()

    <script>
       /* 
       1.js内置对象Date : 
            内置对象 : 由js作者提前写好的,我们直接拿来使用即可。
       */  
      
       //1.创建日期对象
       let d = new Date()
       console.log( d )

       //2.1 转换日期格式
       console.log( d.toLocaleString() )//2021/12/15 下午4:46:16
       console.log( d.toLocaleDateString() )//2021/12/15
       console.log( d.toLocaleTimeString() )//下午4:46:16
       

       //2.2 获取年月日时分秒
       console.log( d.getFullYear() )//2021
       // 1-12月对应0-11下标
       console.log( d.getMonth() )//11下标, 12月
       console.log( d.getDate() )//15
       // 星期天 - 星期六   0-6
       console.log( d.getDay() )//3
       console.log( d.getHours() )//16
       console.log( d.getMinutes() )//47
       console.log( d.getSeconds() )//48
       
       //2.3 获取时间戳
       /* 
       1.时间戳 : 从1970年1月1日格林威治 到现在 秒数
       2.时间戳作用 : 兼容世界时区
       */
       console.log( +d ) // 日期对象转数字
       console.log( Date.now() ) // 时间戳
       
    </script>

03.案例:电商秒杀(setInterval永久定时器)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
      span{
        display: inline-block;
        width: 50px;
        height: 50px;
        background-color: #000;
        color: #fff;
        text-align: center;
        line-height: 50px;
        font-size: 25px;
        font-weight: 700;
      }
    </style>
  </head>
  <body>
    <div>
      <span id="hour">00</span> : <span id="minute">00</span> :
      <span id="second">15</span>
    </div>

    <script>
      /* 秒杀思路
        1.页面一加载,开启间隔 1s 的永久定时器
          1.1 获取当前页面span标签的文本 h m s (转number)
          1.2 s--
          1.3 如果 s < 0,s = 59,m--
          1.4 如果 m < 0, m = 59,h--
          1.5 如果h m s < 10 , 则需要补0
          1.6 将计算之后的结果重新赋值给元素的innerText
          //只是修改h m s的值,并没有修改页面元素的内容
          1.7 清除定时器:h == 0 && m == 0 && s == 0
      */

      let timeID = setInterval( function(){
          //1.1 获取当前页面span标签的文本 h m s (转number)
          let h =  +document.querySelector('#hour').innerText
          let m =  +document.querySelector('#minute').innerText
          let s =  +document.querySelector('#second').innerText
          //1.2 s--
          s--
          //1.3 如果 s < 0,s = 59,m--
          if(s < 0 ){
            s = 59
            m--
          }
          //1.4 如果 m < 0, m = 59,h--
          if(m < 0 ){
            m = 59
            h--
          }
          //1.5 如果h m s < 10 , 则需要补0
          h = h < 10 ? '0' + h : h
          m = m < 10 ? '0' + m : m
          s = s < 10 ? '0' + s : s
          //1.6 将计算之后的结果重新赋值给元素的innerText
          document.querySelector('#hour').innerText = h
          document.querySelector('#minute').innerText = m
          document.querySelector('#second').innerText = s

          //1.7 清除定时器:h == 0 && m == 0 && s == 0
          if( h == 0 && m == 0 && s == 0){
            clearInterval(timeID)
          }
      },1000)
    </script>
  </body>
</html>

04.案例:协议禁用按钮

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
      span{
        display: inline-block;
        width: 50px;
        height: 50px;
        background-color: #000;
        color: #fff;
        text-align: center;
        line-height: 50px;
        font-size: 25px;
        font-weight: 700;
      }
    </style>
  </head>
  <body>
    <div>
      <span id="hour">00</span> : <span id="minute">00</span> :
      <span id="second">15</span>
    </div>

    <script>
      /* 秒杀思路
        1.页面一加载,开启间隔 1s 的永久定时器
          1.1 获取当前页面span标签的文本 h m s (转number)
          1.2 s--
          1.3 如果 s < 0,s = 59,m--
          1.4 如果 m < 0, m = 59,h--
          1.5 如果h m s < 10 , 则需要补0
          1.6 将计算之后的结果重新赋值给元素的innerText
          //只是修改h m s的值,并没有修改页面元素的内容
          1.7 清除定时器:h == 0 && m == 0 && s == 0
      */

      let timeID = setInterval( function(){
          //1.1 获取当前页面span标签的文本 h m s (转number)
          let h =  +document.querySelector('#hour').innerText
          let m =  +document.querySelector('#minute').innerText
          let s =  +document.querySelector('#second').innerText
          //1.2 s--
          s--
          //1.3 如果 s < 0,s = 59,m--
          if(s < 0 ){
            s = 59
            m--
          }
          //1.4 如果 m < 0, m = 59,h--
          if(m < 0 ){
            m = 59
            h--
          }
          //1.5 如果h m s < 10 , 则需要补0
          h = h < 10 ? '0' + h : h
          m = m < 10 ? '0' + m : m
          s = s < 10 ? '0' + s : s
          //1.6 将计算之后的结果重新赋值给元素的innerText
          document.querySelector('#hour').innerText = h
          document.querySelector('#minute').innerText = m
          document.querySelector('#second').innerText = s

          //1.7 清除定时器:h == 0 && m == 0 && s == 0
          if( h == 0 && m == 0 && s == 0){
            clearInterval(timeID)
          }
      },1000)
    </script>
   
  </body>
</html>

04-拓展进阶:关于渲染引擎的重绘与回流介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABcpb77F-1639577454388)(day03.assets/1636883841422.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-62HPJUfP-1639577454390)(day03.assets/1636966604129.png)]

  • 浏览器渲染解析页面完整流程

  • 1.先解析HTML,生成DOM树(重要步骤)

  • 2.后解析CSS,生成样式规则

  • 3.根据DOM树与样式规则,得到一颗渲染树Render Tree(重要步骤)

    • DOM树:只有结构没有样式
    • 渲染数:DOM树 + CSS样式 (可以理解为附加了样式的DOM树)
  • 4.渲染引擎开始工作,解析渲染树。

    • 这个步骤发生 回流(又称重排) : 计算节点的尺寸、结构、布局
  • 5.开始绘制

    • 这个步骤发生重绘 : 根据重排结果进行绘制页面
  • 6.渲染完成,呈现页面

  • 重要概念: 重排一定会引起重绘,但是重绘不一定引起重排

    • 引起重排操作:主要是修改了尺寸、布局(总结起来就是对布局产生印象)
      • 如:修改盒子的尺寸, 修改盒子位置、修改字体大小、边框等等影响盒子模型布局的都会导致重绘
      • 重排:会导致页面大面积重绘,甚至是整个页面重新绘制。(影响性能)
    • 引起重绘操作:不影响布局,只是影响盒子自身属性
      • 如:修改颜色,修改透明度等,对布局没有任何影响的

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这里是一个简单的示例,使用PHP和jQuery实现基本的增删改查功能。 假设我们有一个名为“users”的数据库表,其中包含以下字段:id、name、email、phone。我们将创建一个Web应用程序,使用户能够执行以下操作: - 显示所有用户 - 添加新用户 - 编辑用户信息 - 删除用户 以下是实现这些功能的代码: index.php: ```html <!DOCTYPE html> <html> <head> <title>AJAX CRUD Example with PHP and jQuery</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="script.js"></script> </head> <body> <h1>AJAX CRUD Example with PHP and jQuery</h1> <div id="users"> <table> <tr> <th>ID</th> <th>Name</th> <th>Email</th> <th>Phone</th> <th>Action</th> </tr> </table> </div> <br> <div id="add_user"> <h2>Add User</h2> <form id="add_user_form"> <label>Name:</label> <input type="text" name="name" required> <br><br> <label>Email:</label> <input type="email" name="email" required> <br><br> <label>Phone:</label> <input type="text" name="phone" required> <br><br> <button type="submit">Add User</button> </form> </div> </body> </html> ``` script.js: ```javascript $(document).ready(function() { // 显示所有用户 showUsers(); // 添加用户 $('#add_user_form').submit(function(event) { event.preventDefault(); var name = $('input[name="name"]').val(); var email = $('input[name="email"]').val(); var phone = $('input[name="phone"]').val(); $.ajax({ url: 'add_user.php', type: 'POST', data: {name: name, email: email, phone: phone}, success: function(data) { alert('User added successfully'); showUsers(); } }); }); // 编辑用户信息 $(document).on('click', '.edit_user', function() { var id = $(this).data('id'); $('#edit_user_form').attr('data-id', id); $.ajax({ url: 'get_user.php', type: 'POST', data: {id: id}, success: function(data) { var user = JSON.parse(data); $('input[name="edit_name"]').val(user.name); $('input[name="edit_email"]').val(user.email); $('input[name="edit_phone"]').val(user.phone); } }); }); $('#edit_user_form').submit(function(event) { event.preventDefault(); var id = $(this).data('id'); var name = $('input[name="edit_name"]').val(); var email = $('input[name="edit_email"]').val(); var phone = $('input[name="edit_phone"]').val(); $.ajax({ url: 'edit_user.php', type: 'POST', data: {id: id, name: name, email: email, phone: phone}, success: function(data) { alert('User updated successfully'); showUsers(); } }); }); // 删除用户 $(document).on('click', '.delete_user', function() { var id = $(this).data('id'); $.ajax({ url: 'delete_user.php', type: 'POST', data: {id: id}, success: function(data) { alert('User deleted successfully'); showUsers(); } }); }); }); function showUsers() { $.ajax({ url: 'get_users.php', type: 'GET', success: function(data) { var users = JSON.parse(data); $('#users table').empty(); $('#users table').append('<tr><th>ID</th><th>Name</th><th>Email</th><th>Phone</th><th>Action</th></tr>'); $.each(users, function(i, user) { $('#users table').append('<tr><td>' + user.id + '</td><td>' + user.name + '</td><td>' + user.email + '</td><td>' + user.phone + '</td><td><button class="edit_user" data-id="' + user.id + '">Edit</button> <button class="delete_user" data-id="' + user.id + '">Delete</button></td></tr>'); }); } }); } ``` get_users.php: ```php <?php $conn = mysqli_connect('localhost', 'username', 'password', 'database'); $result = mysqli_query($conn, 'SELECT * FROM users'); $users = array(); while ($row = mysqli_fetch_assoc($result)) { $users[] = $row; } echo json_encode($users); ?> ``` add_user.php: ```php <?php $conn = mysqli_connect('localhost', 'username', 'password', 'database'); $name = mysqli_real_escape_string($conn, $_POST['name']); $email = mysqli_real_escape_string($conn, $_POST['email']); $phone = mysqli_real_escape_string($conn, $_POST['phone']); mysqli_query($conn, "INSERT INTO users (name, email, phone) VALUES ('$name', '$email', '$phone')"); ?> ``` get_user.php: ```php <?php $conn = mysqli_connect('localhost', 'username', 'password', 'database'); $id = mysqli_real_escape_string($conn, $_POST['id']); $result = mysqli_query($conn, "SELECT * FROM users WHERE id=$id"); $user = mysqli_fetch_assoc($result); echo json_encode($user); ?> ``` edit_user.php: ```php <?php $conn = mysqli_connect('localhost', 'username', 'password', 'database'); $id = mysqli_real_escape_string($conn, $_POST['id']); $name = mysqli_real_escape_string($conn, $_POST['name']); $email = mysqli_real_escape_string($conn, $_POST['email']); $phone = mysqli_real_escape_string($conn, $_POST['phone']); mysqli_query($conn, "UPDATE users SET name='$name', email='$email', phone='$phone' WHERE id=$id"); ?> ``` delete_user.php: ```php <?php $conn = mysqli_connect('localhost', 'username', 'password', 'database'); $id = mysqli_real_escape_string($conn, $_POST['id']); mysqli_query($conn, "DELETE FROM users WHERE id=$id"); ?> ``` 这些代码将创建一个简单的Web应用程序,用户可以使用它来执行基本的增删改查操作,而无需刷新页面。当用户执行任何操作时,都会使用AJAX通过PHP与MySQL数据库进行通信。 ### 回答2: PHP AJAX 实现增删改查是一种常用的Web开发技术,可以提供实时的数据交互和无需刷新页面的操作体验。下面以一个简单的用户信息管理作为例子进行说明: 增加操作(Create):通过AJAX发送请求,将用户输入的信息传递给PHP后台,PHP将信息插入数据库中,然后将插入结果返回给前端页面,可以实现实时更新显示。 删除操作(Delete):通过AJAX发送请求,将要删除的用户id传递给PHP后台,PHP根据接收到的id删除相应的用户数据,然后将删除结果返回给前端页面。 修改操作(Update):通过AJAX发送请求,将用户修改的信息以及要修改的用户id传递给PHP后台,PHP根据id更新数据库中的用户信息,然后将更新结果返回给前端页面。 查询操作(Retrieve):通过AJAX发送请求,将查询条件传递给PHP后台,PHP根据条件从数据库中检索相应的用户信息,然后将查询结果返回给前端页面。 在实现增删改查的过程中,可以使用jQuery等库来简化AJAX的操作,并使用JSON格式进行数据的传输。同时,为了保证数据的安全性和完整性,需要对用户输入进行合法性验证,并使用prepared statement等方式来防止SQL注入攻击。 总之,PHP AJAX 实现增删改查可以提高用户体验和操作效率,实现数据的实时交互和无刷新更新。同时,开发者需要注意数据的安全性和完整性,以及代码的健壮性和可维护性。 ### 回答3: PHP和Ajax是两种不同的编程语言和技术,在Web开发中常常一起使用来实现增删改查(CRUD)操作。 增(Create)操作是指向数据库中插入新的数据。当用户提交表单时,PHP可以接收到表单的数据并将其插入数据库中,然后通过Ajax向服务器发送请求,更新页面上的数据,以显示新的数据。 删(Delete)操作是指从数据库中删除数据。当用户点击删除按钮时,Ajax会向服务器发送请求,并通过PHP来删除数据库中的数据,然后通过Ajax更新页面上的数据,以实现删除效果。 改(Update)操作是指修改数据库中的数据。当用户编辑某个数据时,通过Ajax向服务器发送请求,PHP接收到请求后,会将修改的数据更新到数据库中,然后通过Ajax更新页面上的数据,以显示修改后的数据。 查(Read)操作是指从数据库中获取数据。当用户需要查看某个数据时,通过Ajax向服务器发送请求,PHP接收到请求后,会从数据库中获取对应的数据,并通过Ajax返回给前端,然后前端使用Ajax来更新页面上的数据,以显示查询结果。 综上所述,通过PHP和Ajax可以实现增删改查操作。当用户进行相关操作时,通过Ajax向服务器发送请求,PHP接收请求并处理数据库操作,然后通过Ajax更新页面上的数据,以达到实时更新和操作的效果。这种方式可以提升用户体验,减少刷新页面的次数,更加灵活和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值