WEBAPIS知识案例总结(续)

其他事件

页面加载事件

  • 加载外部资源(如图片,外联css和js等)加载完毕时触发的事件
  • 有时候需要等页面资源全部处理完之后做一些事情
  • 老代码喜欢把script写在head中,这时候直接找dom元素找不到
  • 事件名:load
  • 监听页面所有资源加载完毕:给windows添加load事件
    //等待页面所有资源加载完毕,就去执行回调函数
    window.addEventListener('load',function(){
      const btn=document.querySelector('button')
      btn.addEventListener('click',function(){
        alert(11)
      })
    })
    img.addEventListener('load',function(){
      //等待图片加载完毕 再去执行里面的代码
    })

 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件

  • 当初始的 HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表,图像等完全加载
  • 事件名:DOMContentLoaded
  • 监听页面DOM加载完毕:给DOMContentLoaded事件
    document.addEventListener('DOMContentLoaded',function(){
      
    })

元素滚动事件

  • 滚动条在滚动的时候持续触发的事件
  • 很多网页需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部
  • 事件名:scroll
  • 监听整个页面滚动:
    window.addEventListener('scroll',function(){

      console.log('滚了')
    })
  • 页面出现滚动条之后才有用 
  • 给window或document添加scroll事件
  • 监听某个元素的内部滚动直接给某个元素添加即可

获取位置

scrollLeft和scrollTop(属性)
  • 获取被卷去的大小
  • 获取元素内容往左,往上滚出去看不到的距离
  • 这两个值是可读写的
<!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>
    body {
      padding: 100px;
      height: 3000px;
    }
    div {
      display: none;
      overflow: scroll;
      margin: 100px;
      width: 200px;
      height: 200px;
      border: 1px solid #000;
    }
  </style>
 
</head>
<body>
  <!-- <button>点击</button> -->
  <div>
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    <script>
       document.documentElement.scrollTop=800//可改写
      const div=document.querySelector('div')
      window.addEventListener('scroll',function(){
        const n=document.documentElement.scrollTop//返回数字型 不带单位
        if(n>=100){
          div.style.display='block'
        }
        else {
          div.style.display='none'
        }
      })
    //   const div=document.querySelector('div')
    //   div.addEventListener('scroll',function(){
    //     console.log(111)
    //     console.log(div.scrollTop)
    //   })
    // </script>
</body>
</html>

小tip:

  • document.body可获得body标签
  • document.documentElement可获得html标签

页面滚动显示隐藏侧边栏

  //获取元素
  const elevator=document.querySelector('.xtx-elevator')
  //1.当页面滚动大于300px,就显示电梯导航
  //2.给页面添加滚动事件
  window.addEventListener('scroll',function(){
    //被卷去的头部大于300
    const n=document.documentElement.scrollTop
    // if(n>=300){
    //   elevator.style.opacity=1
    // }
    // else {
    //   elevator.style.opacity=0
    // }
    elevator.style.opacity=n>300?1:0
  })
  //点击返回页面顶部
  const backTop=document.querySelector('#backTop')
  backTop.addEventListener('click',function(){
    //可读写
    // document.documentElement.scrollTop=0
    window.scrollTo(0,0)
  })

tip:

页面滚动事件-滚动到指定的坐标

  • scrollTo()方法可把内容滚动到指定的坐标
  • 语法:元素.scrollTo(x,y)
  //让页面滚动到y轴1000px的位置
  window.scrollTo(0,1000)

页面尺寸事件

会在窗口尺寸改变的时候触发事件:

resize

    //resize浏览器窗口大小发生变化的时候触发的事件
    window.addEventListener('resize',function(){
      console.log(1)
    })

获取元素宽高

获取宽高:

  • 获取元素的可见部分宽高(不包含边框,margin,滚动条等,包含padding)
  • clientWith和clientHeight 
    const div=document.querySelector('div')
    console.log(div.clientWidth)
    //resize浏览器窗口大小发生变化的时候触发的事件
    window.addEventListener('resize',function(){
      console.log(1)
    })

元素的尺寸和位置

使用场景:

  • 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事。‘
  • 简单说,就是通过js的方式,得到元素在页面中的位置
  • 这样我们就可以做,页面滚动到这个位置,就可以做某些操作,省去计算了

获取宽高:

  • 获取元素的自身宽高,包含元素自身设置的宽高、padding,border
  • offsetWidth和offsetHeight
  • 获取出来的是数值,方便计算
  • 注意:获取的是可视宽高,如果盒子是隐藏的,获取的结果是0

获取位置:

  • 获取元素距离自己定位父级元素的左,上距离(最近一级带有定位的祖先元素)
  • offsetLeft和offsetTop 注意是只读属性
    const div=document.querySelector('div')
    console.log(div.offsetLeft)

仿京东固定导航案例

需求:当页面滚动到秒杀模块,导航栏自动滑入,否则滑出

分析:

  1. 用到页面滚动事件
  2. 检测页面滚动大于等于秒杀模块的位置则滑入,否则滑出
  3. 主要移动的是秒杀模块的顶部位置

        const sk=document.querySelector('.sk')
        const header=document.querySelector('.header')
        // 1.页面滚动事件
        window.addEventListener('scroll',function(){
            //当页面滚动到秒杀模块时,就改变头部的top值
            //页面被卷去的头部>=秒杀模块的位置offsetTop
            const n=document.documentElement.scrollTop
            if(n>=sk.offsetTop){
                header.style.top=0
            }
            else {
                header.style.top='-80px'
            }
        })

实现哔哩哔哩点击小滑块移动效果

需求:当点击链接,下面红色滑块跟着移动

分析:

  1. 用到时间委托
  2. 点击链接得到当前元素的offsetLeft值
  3. 修改line颜色块的transform值=点击链接的offsetLeft
  4. 添加过渡效果
    // 1. 事件委托的方法 获取父元素 tabs-list
    const list = document.querySelector('.tabs-list')
    const line = document.querySelector('.line')
    // 2. 注册点击事件
    list.addEventListener('click', function (e) {
      // 只有点击了A 才有触发效果
      if (e.target.tagName === 'A') {
        // console.log(11)
        // 当前元素是谁 ?  e.target
        // 得到当前点击元素的位置
        // console.log(e.target.offsetLeft)
        // line.style.transform = 'translateX(100px)'
        // 把我们点击的a链接盒子的位置  然后移动
        line.style.transform = `translateX(${e.target.offsetLeft}px)`
      }
    })

获取位置

element.getBoundingClientRect()

方法返回元素的大小及其相对于视口的位置

区别于offsetTop:offsetTop是相对于整个页面来说的,而getVBoundingClientRect()是相对于视口来说,如果滚动整个界面,则位置坐标就会改变

总结

属性作用说明
scrollLeft和scrollTop被卷去的头部和左侧配合页面滚动来写,可读写
clientWidth和clientHeight获得元素宽高不包含border,margin,滚动条用于js获取元素的大小,只读属性
offsetWidth和offsetHeight获取元素宽度和高度包含border,padding,滚动条等,只读
offsetLeft和offsetTop获取元素距离自己定位父级元素的左,上距离获取元素位置的时候使用,只读属性

 电梯导航综合案例

需求:点击不同的模块,页面可以自动跳转不同的位置

模块分析

  1. 页面滚动到对应的位置,导航显示,否则隐藏模块
  2. 点击导航对应小模块,页面会跳到对应大模块的位置
  3. 页面滚动到对应位置,电梯导航对应模块自动发生变化
  1. 显示隐藏电梯盒子和返回顶部已经完成,可以放到自执行函数里面,防止变量污染
  2. 电梯模块单独放到自执行函数里面

模块分析2:点击每个模块,页面自动滚动到对应模块,使用事件委托方法更加简单

  1. 点击小模块,当前添加active类名
  2. 解决初次获取不到active报错的问题 

解决方案:

  • 不能直接获取这个类,然后移除,这样会报错
  • 先获取这个类,然后加个判断:如果有这个类,就移除,如果没有,返回null,就不执行移除,就不报错了

点击每个模块,页面跳转至对应大盒子位置

核心思想:

  1. 把对应大盒子的offsetTop'给document.documentElement.scrollTop
  2. 我们发现小盒子li的自定义属性里面值跟大盒子后面一致
  3. 利用模板字符串 把点击的自定义属性给大盒子 就找到对应的大盒子了
  4. 然后拿到这个大盒子的offsetTop值给·document.documentElement.scrollTop即可·

模块分析3:页面滚动到大盒子位置,电梯导航小盒子对应模块自动处于选中状态

  1. 当页面滚动了,先移除所有小li里面a的状态 active防止有多个active
  2. 因为页面滚动需要不断获取大盒子的位置,所以需要把所有的大盒子都获取过来
  3. 开始进行滚动判断
  • 如果页面滚动大于大盒子的offsetTop 并且小于下一个大盒子的offsetTop就把对应的小盒子拿出来添加类
  • 以此类推
  • 最后一个,如果大于等于最新专题模块,就选出最后一个对应小盒子(更精确)
    // 第一模块 页面滑动可以显示和隐藏
  (function(){
//获取元素
const entry=document.querySelector('.xtx_entry')
  const elevator=document.querySelector('.xtx-elevator')
  //1.当页面滚动大于300px,就显示电梯导航
  //2.给页面添加滚动事件
  window.addEventListener('scroll',function(){
    //被卷去的头部大于300
    const n=document.documentElement.scrollTop
    // if(n>=300){
    //   elevator.style.opacity=1
    // }
    // else {
    //   elevator.style.opacity=0
    // }
    elevator.style.opacity=n>entry.offsetTop?1:0
  })
  //点击返回页面顶部
  const backTop=document.querySelector('#backTop')
  backTop.addEventListener('click',function(){
    //可读写
    // document.documentElement.scrollTop=0
    window.scrollTo(0,0)
  })
  })();
  //第二第三到放到另外一个执行函数里面
  (function(){
    const list=document.querySelector('.xtx-elevator-list')
    list.addEventListener('click',function(e){
      //console.log(11)
      if(e.target.tagName==='A'&&e.target.dataset.name){
        //排他思想
        //先移除原来的类active
        //先获取这个类名
        //若找不到该类名,就返回空null
        const old=document.querySelector('.xtx-elevator-list .active')
        //判断
        if(old){
          old.classList.remove('active')
        }
          //当前元素添加active
        e.target.classList.add('active')
        // 获得自定义属性
        // console.log(e.target.dataset.name)
        // 根据小盒子的自定义属性值去选择 对应的大盒子
        // console.log(document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTop)
        const top=document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTop
        // 让页面滚动到对应的位置
        document.documentElement.scrollTop=top
      }
    })
  // 3.页面滚动事件 可以根据大盒子选 添加active类
        
        window.addEventListener('scroll',function(){
          //先获取这个类名
        //若找不到该类名,就返回空null
          const old=document.querySelector('.xtx-elevator-list .active')
        //判断
        if(old){
          old.classList.remove('active')
        }
        // 判断当前页面滑动的位置 选择小盒子
        //获取四个大盒子
        const news=document.querySelector('.xtx_goods_new')
        const popular=document.querySelector('.xtx_goods_popular')
        const brand=document.querySelector('.xtx_goods_brand')
        const topic=document.querySelector('.xtx_goods_topic')
        const n=document.documentElement.scrollTop
        if(n>=news.offsetTop&&n<popular.offsetTop){
          //选择第一个小盒子
          document.querySelector('[data-name=new]').classList.add('active')
        }else if(n>=popular.offsetTop&&n<brand.offsetTop){
          document.querySelector('[data-name=popular]').classList.add('active')

        }else if(n>=brand.offsetTop&&n<topic.offsetTop){
          document.querySelector('[data-name=brand]').classList.add('active')

        }else if(n>=topic.offsetTop){
          document.querySelector('[data-name=topic]').classList.add('active')

        }
        })
  
  })();

tip:

html {

  scroll-behavior: smooth;//让滚动条添加滑动效果

}

 日期对象

  • 日期对象:用来表示时间的对象
  • 作用:可以得到当前系统的时间

实例化

  • 在代码中发现了new关键字时,一般将这个操作称为实例化
  • 创建一个事件对象并获取时间
  • 获取当前时间 const date=new Date()
  • 获得指定时间 const date=new Date('2008-8-8')
    //实例化 new
    // const date=new Date()
    // console.log(date)
    // 获得指定时间
    const date=new Date('2008-8-8 08:30:00')
    console.log(date)

事件对象方法

使用场景:因为日期对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用格式

方法作用说明
getFullYear()获得年份获取四位年份
getMonth()获得月份取值为0~11
getDate()获取月份中的每一天不同月份取值也不相同
getDay()获取星期取值为0~6
getHours()获取小时取值为0~23
getMinutes()获取分钟取值为0~59
getSeconds()获取秒取值为0~59

页面显示时间

需求:将当前时间以:YYYY-MM-DD HH:mm形式显示在页面 2008-08-08 08:08

分析: 

  1. 调用日期对象方法进行转换
  2. 记得数字要补0
  const div=document.querySelector('div')
  function getMydate(){
    const date=new Date()
    let h=date.getHours()
    let m=date.getMinutes()
    let s=date.getSeconds()
    h=h<10?'0'+h:h
    m=m<10?'0'+m:m
    s=s<10?'0'+s:s
    return `今天是:${date.getFullYear()}年${date.getMonth()+1}月${date.getDate()}号 ${h}:${m}:${s}`
  }
  div.innerHTML=getMydate()//确保页面刷新之后立刻就出现时间
  
  setInterval(function(){
  div.innerHTML=getMydate()

  },1000)

时间的另外一种写法

  //得到日期对象
  const date=new Date()
  div.innerHTML=date.toLocaleDateString()// 2024/4/1
  div.innerHTML=date.toLocaleString()//2024/4/1 21:00:15
  div.innerHTML=date.toLocaleTimeString()//21:01:16

时间戳

  • 使用场景:如果计算倒计时效果,前面方法无法直接计算,需要借助于时间戳完成
  • 什么是时间戳:是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
  • 算法:
  • 将来的时间戳 -现在的时间戳=剩余时间毫秒数
  • 剩余时间毫秒数 转换为剩余时间的年月日时分秒就是倒计时时间
  • 比如 将来时间戳 2000ms - 现在时间戳1000ms=1000ms
  • 1000ms转换为就是0小时0分1秒

三种方式获取时间戳:

1、使用getTime()方法

2、简写 +new Date()  (无需实例化

3、使用Date.now()    (无需实例化

但是只能得到当前的时间戳,而前面两种可以返回指定时间的时间戳

    // 1.getTime()
    const date=new Date()
    console.log(date.getTime())
    // 2.+new Date()
    console.log(+new Date())
    // 3.Date.now()
    console.log(Date.now())
  console.log(+new Date())
    console.log('---------------')
    //返回指定时间
    console.log(+new Date('2022-4-1 18:30:00'))

返回星期

    const arr=['星期天','星期一','星期二','星期三','星期四','星期五','星期六']
    console.log(arr[new Date().getDay()])

毕业倒计时

需求:计算到下课还有多少时间

分析:

  1. 用将来的时间减去现在的时间就是剩余的时间
  2. 核心:使用将来的时间戳减去现在的时间戳
  3. 把剩余的时间转换为天 时 分 秒

注意:

1.通过时间戳得到的时毫秒,需要转换为秒再计算

2.转换公式:

    d=parseInt(总秒数/60/60/24);//计算天数
    h=parseInt(总秒数/60/60%24);//计算小时
    m=parseInt(总秒数/60%60);//计算分数
    s=parseInt(总秒数%60);//计算秒数
        // 1.自定义一个随机颜色函数
        function getRandomcolor(flag=true){
      if(flag){
        let str='#'
        let arr=['0','1' ,'2','3','4','5','6','7','8','9','a','b','c','d','e','f']
        //利用for循环循环六次,累加到str里面
        for(let i=1;i<=6;i++){
          let Random=Math.floor(Math.random()*arr.length)
          str+=arr[Random]
        }
        return str
      }
      else{
        let r=Math.floor(Math.random()*256)
        let g=Math.floor(Math.random()*256)
        let b=Math.floor(Math.random()*256)
        return `rgb(${r},${g},${b})`
      }
    }
    const countdown=document.querySelector('.countdown')
    countdown.style.backgroundColor=getRandomcolor(true)
    
    //函数封装 getCountTime
    function getCountTime(){
      const next=document.querySelector('.next')
    function gettime(){
      let date=new Date()
      return `今天是${date.getFullYear()}年${date.getMonth()+1}月${date.getDate()}日`
    }
    next.innerHTML=gettime()
    // 1.得到当前的时间戳
    const now=+new Date()
    // 2.得到将来的时间戳
    const last=+new Date('2024-4-1 23:00:00')
    // 3.得到剩余的时间戳 count 记得转化为秒数
    const count=(last-now)/1000
    // 转换为时分秒
    let d=parseInt(count/60/60/24)
    let h=parseInt(count/60/60%24)//计算小时
    let m=parseInt(count/60%60)//计算分数
    let s=parseInt(count%60)//计算秒数
    h=h<10?'0'+h:h
    m=m<10?'0'+m:m
    s=s<10?'0'+s:s
    // console.log(d,h,m,s)
    // 5.把时分秒写到对应的盒子里面
    const hour=document.querySelector('#hour')
    const minutes=document.querySelector('#minutes')
    const second=document.querySelector('#second')
    hour.innerHTML=h
    minutes.innerHTML=m
    second.innerHTML=s
    }
    getCountTime()
    // 开启定时器
    setInterval(getCountTime,1000)

节点操作

DOM节点

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

节点类型

元素节点
  • 所有的标签 比如body、div
  • html是根节点
属性节点
  • 所有的属性 比如 href
文本节点
  • 所有的文本
其他

查找节点

关闭二维码案例:

  • 点击关闭按钮,关闭的是二维码的盒子,还要获取二维码盒子
  • 关闭按钮和二维码之间是父子关系
  • 所以我们可以这么做,直接关闭他的爸爸,就无需获取二维码元素了

节点关系:针对的找亲戚返回的都是对象

  • 父节点

parentNode属性

返回最近一级的父节点 找不到返回null

子元素.parentNode

   const close=document.querySelectorAll('.close')
    for(let i=0;i<close.length;i++){
      close[i].addEventListener('click',function(){
        this.parentNode.style.display='none'//按钮的父元素即为盒子,其父元素不再显示
      })
    }
  • 子节点

childNodes

获得所有的子节点,包括文本节点(空格,换行)、注释节点等

children 属性 (重点)
  • 仅获得所有元素的节点
  • 返回的还是一个伪数组

父元素.children

  const ul=document.querySelector('ul')
  console.log(ul.children)//得到伪数组 选择的是亲儿子
  • 兄弟节点

兄弟关系查找

1.下一个兄弟节点

nextElementSibling属性

2.上一个兄弟节点

previousElementSibling属性

  console.log(li2.previousElementSibling)//上一个兄弟
  console.log(li2.nextElementSibling)//下一个兄弟

增加节点

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

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

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

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

追加节点

  • 要想在页面中看到,还得插入到某个父元素中
  • 插入到父元素的最后一个子元素:
    父元素.appendChild(插入的元素)
    document.body.appendChild(div)

在ul里末尾添加li元素

<body>
  <ul></ul>
  <script>
    const ul=document.querySelector('ul')
    const li=document.createElement('li')
    li.innerHTML='我是li'
    ul.appendChild(li)
  </script>
</body>

     

  • 插入到父元素的某个子元素的前面
    //插入到某个子元素的前面
    父元素.insertBefore(要插入的元素,在哪个元素前面)
    ul.insertBefore(li,ul.children[0])//放在数组第一个元素前面

创建节点

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

创建元素节点方法:

    const div =document.createElement('div')

 学成在线案例渲染

需求:按照数据渲染界面

分析:

  1. 准备好空的ul结构
  2. 根据数据的个数,创建一个新的空li
  3. li里面添加img标题等
  4. 追加给ul
        // 1. 重构  
        let data = [
            {
                src: 'images/course01.png',
                title: 'Think PHP 5.0 博客系统实战项目演练',
                num: 1125
            },
            {
                src: 'images/course02.png',
                title: 'Android 网络动态图片加载实战',
                num: 357
            },
            {
                src: 'images/course03.png',
                title: 'Angular2 大前端商城实战项目演练',
                num: 22250
            },
            {
                src: 'images/course04.png',
                title: 'Android APP 实战项目演练',
                num: 389
            },
            {
                src: 'images/course05.png',
                title: 'UGUI 源码深度分析案例',
                num: 124
            },
            {
                src: 'images/course06.png',
                title: 'Kami2首页界面切换效果实战演练',
                num: 432
            },
            {
                src: 'images/course07.png',
                title: 'UNITY 从入门到精通实战案例',
                num: 888
            },
            {
                src: 'images/course08.png',
                title: 'Cocos 深度学习你不会错过的实战',
                num: 590
            },
        ]
        const ul = document.querySelector('.box-bd ul')
        // 1. 根据数据的个数,创建 对应的小li
        for (let i = 0; i < data.length; i++) {
            // 2. 创建新的小li
            const li = document.createElement('li')
            // 把内容给li 属性之间记得保留空格
            li.innerHTML = `
                <a href="#">
                    <img src=${data[i].src} alt="">
                    <h4>
                        ${data[i].title}
                    </h4>
                    <div class="info">
                        <span>高级</span> • <span>${data[i].num}</span>人在学习
                    </div>
                </a>
            `
            // 3. ul追加小li
            ul.appendChild(li)
        }

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

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

克隆节点

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

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

  • 若为true,则代表克隆时会包含后代节点一起克隆,深克隆
  • 若为false,则代表克隆时不包含后代节点,只克隆标签,不克隆内容,浅克隆
  • 默认为false 
    //克隆一个节点并追加到ul元素的最后面
    const ul=document.querySelector('ul')
    //1.克隆节点 元素.cLoneNode(true)
    const li1=ul.children[0].cloneNode(true)
    ul.appendChild(li1)

删除节点

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

语法:父元素.removeChild(要删除的元素)

    const ul=document.querySelector('ul')
    ul.removeChild(ul.children[0])

注:

  • 如果不存在父子关系则删除不成功
  • 删除节点和隐藏节点(display)有区别的:隐藏节点还是存在的,但是删除,则从html中删除节点

M端事件

移动端也有自己独特的地方,比如触屏事件touch(也称触摸事件),Android和IOS都有

  • 触屏事件touch(也称触摸事件),Andiroid和IOS都有
  • touch对象代表一个触摸点,触摸点可能是一根手指,也可能是一根触摸笔,触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。
  • 常见的触屏事件如下:
触屏touch事件说明
touchstart手指触摸到一个DOM元素时触发
touchmove手指在一个DOM元素上滑动时触发
touchend手指从一个DOM元素上移开时触发

插件

插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
学习插件的基本过程

  • 熟悉官网,了解这个插件可以完成什么需求  https://www.swiper.com.cn/
  • 看在线演示,找到符合自己需求的demo https://www.swiper.com.cn/demo/index.html
  • 查看基本使用流程 https://www.swiper.com.cn/usage/index.html
  • 查看APi文档,去配置自己的插件 https://www.swiper.com.cn/api/index.html
  • 注意:多个swiper同时使用的时候,类名需要注意区分

插件的具体使用参见pink老师124-swiper的使用

 学生信息表案例

业务模块:

  1. 点击按钮可以录入数据
  2. 点击删除可以删除当前的数据
  • 本次案例,尽量减少dom操作,采取操作数据的形式
  • 增加和删除都是针对于数组的操作,然后根据数组数据渲染页面

核心思路:

  • 声明一个空数组
  • 点击录入,根据相关数据,生成对象,追加到数组里面

点击录入模块

1.首先取消表单默认提交事件

2.创建新的对象,里面存储表单获取过来的数据

  • 根据数组数据渲染页面-表格的行
  • 点击删除按钮,删除的是对应数组里面的数据
  • 再次根据数组的数据,渲染页面

3.追加给数组

4.渲染数据,遍历数组,动态生成tr,里面填写对应td数据,并追加给tbody

5.重置表单

6..注意防止多次生成多条数据,先清空tbody

点击删除模块

1.采用事件委托形式,给tbody注册点击事件

2.点击链接,要删除的是对应数组里面的这个数据,而不是dom节点

点击新增需要验证表单

1.获取所有需要填写的表单,他们共同特点都有name属性

2.遍历这些表单,如果有一个值为空,则return返回提示输入为空中断程序

3.注意书写的位置,应该放到新增数据的前面,阻止默认行为的后面

<!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>
  <link rel="stylesheet" href="css/index.css" />
</head>

<body>
  <h1>新增学员</h1>
  <!-- autoplaycomplete='off' 不会显示之前输入过的内容 -->
  <form class="info" autocomplete="off">
    姓名:<input type="text" class="uname" name="uname" />
    年龄:<input type="text" class="age" name="age" />
    性别:
    <select name="gender" class="gender">
      <option value="男">男</option>
      <option value="女">女</option>
    </select>
    薪资:<input type="text" class="salary" name="salary" />
    就业城市:<select name="city" class="city">
      <option value="北京">北京</option>
      <option value="上海">上海</option>
      <option value="广州">广州</option>
      <option value="深圳">深圳</option>
      <option value="曹县">曹县</option>
    </select>
    <button class="add">录入</button>
  </form>

  <h1>就业榜</h1>
  <table>
    <thead>
      <tr>
        <th>学号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>性别</th>
        <th>薪资</th>
        <th>就业城市</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>
      <!-- 
        <tr>
          <td>1001</td>
          <td>欧阳霸天</td>
          <td>19</td>
          <td>男</td>
          <td>15000</td>
          <td>上海</td>
          <td>
            <a href="javascript:">删除</a>
          </td>
        </tr> 
        -->
    </tbody>
  </table>
  <script>
    //获取元素
    const uname=document.querySelector('.uname')
    const age=document.querySelector('.age')
    const gender=document.querySelector('.gender')
    const salary=document.querySelector('.salary')
    const city=document.querySelector('.city')
    const tbody=document.querySelector('tbody')
    // 获取所有带有name属性的元素
    const items=document.querySelectorAll('[name]')
    //声明一个空的数组 增加和删除都是对这个数组进行操作
    const arr=[]
    // 1.录入模块
    // 1.1表单提交事件
    const info=document.querySelector('.info')
    info.addEventListener('submit',function( e){
      //阻止form默认行为 点击提交之后不跳转至新页面
      e.preventDefault()
      // 这里进行表单验证 如果不通过 直接中断 不需要添加数据
      // 先遍历循环
      for(let i=0;i<items.length;i++){
        if(items[i].value===''){
          return alert('输入内容不能为空')
        }
      }
      // console.log(11)
      //创建新的对象
      const obj={
        stuID:arr.length+1,
        uname:uname.value,
        age:age.value,
        gender:gender.value,
        salary:salary.value,
        city:city.value
      }
      // console.log(obj)
      //追加到数组里面
      arr.push(obj)
      // console.log(arr)
      //提交之后输入表单
      this.reset()//重置表单 恢复默认状态
      //调用渲染函数
      render()
    })
    function render(){
      //先清空tbody,把最新数组里面的数据渲染完毕
      tbody.innerHTML=''
      // 遍历数组
      for(let i=0;i<arr.length;i++){
        //生成tr
        const tr=document.createElement('tr')
        tr.innerHTML=`
          <td>${arr[i].stuID}</td>
          <td>${arr[i].uname}</td>
          <td>${arr[i].age}</td>
          <td>${arr[i].gender}</td>
          <td>${arr[i].salary}</td>
          <td>${arr[i].city}</td>
          <td>
            <a href="javascript:" data-id=${i}>删除</a>
          </td>
        `
        // 追加元素 父元素.appendChild(子元素)
        tbody.appendChild(tr)
      }
    }
    // 3.删除操作
    // 3.1事件委托 tbody
    tbody.addEventListener('click',function(e){
      if(e.target.tagName==='A'){
        //得到当前元素的自定义属性 data-id
        // console.log(e.target.dataset.id)
        // 删除arr 数组里面对应的数据
        arr.splice(e.target.dataset.id,1)
        // 重新渲染一次
        render()
      }
    })
  </script>

</body>

</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/522346.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【热门话题】Stable Diffusion:本地部署教程

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Stable Diffusion&#xff1a;本地部署教程一、引言二、环境准备1. 硬件配置2. …

考研数学|怎样刷题更有效率?这些坑千万别踩!

考研数学刷题的这些困扰相信大部分的同学都是有的&#xff0c;为此我整理了一些提高考研数学刷题效率的方法和策略&#xff0c;希望能帮助你更有效地学习和解题。 首先要制定合理的刷题计划&#xff0c;首先遵循“教材→视频→全书或辅导讲义→习题集→真题→专项训练→模拟套…

vue项目开发实战案例

目录 项目概述 1. 项目初始化 2. 商品展示 3. 购物车管理 4. 订单处理 5. 路由管理 6. 样式和交互优化 7. 部署和测试 总结 Vue.js 是一种流行的前端 JavaScript 框架&#xff0c;广泛应用于现代 Web 开发中。下面是一个简单的 Vue 项目开发实战案例&#xff0c;涵盖了…

C++的并发世界(七)——互斥锁

0.死锁的由来 假设有两个线程T1和T2&#xff0c;它们需要对两个互斥量mtx1和mtx2进行访问。而且需要按照以下顺序获取互斥量的所有权&#xff1a; -T1先获取mte1的所有权,再获取mt2的所有权。 -T2先获取 mtx2的所有权。再铁取 mtx1的所有权。 如果两个线程同时执行&#xff0c…

Redis主从复制、哨兵模式、Cluster集群

目录 一、Redis主从复制 1、主从复制介绍 2、主从复制原理 ​编辑 3、主从复制的作用 4.Redis主从复制实验搭建 1. 关闭防火墙和安装依赖环境 2. 解压安装包 3. 编译并安装到指定目录 4. 执行脚本文件 5. 做软连接 6. 启动redis并查看端口 7. 重启redis 8. 修改主…

秋招刷题4(动态规划)

1.购物单 import java.util.Scanner;public class Main {public static void main(String[] args){Scanner sc new Scanner(System.in);int N sc.nextInt();int m sc.nextInt();Goods[] goods new Goods[m];for(int i 0; i < m; i){goods[i] new Goods();}for(int i …

Matlab|含氢微网优化调度模型

目录 1 主要内容 模型示意图 目标函数 2 部分程序 3 程序结果 4 下载链接 1 主要内容 最近咨询含氢微网优化调度模型的同学较多&#xff0c;本次就分享一个高质量的源码资源。该程序方法复现《Simulation of design and operation of hydrogen energy utilization system…

数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成

数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成 目录 数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成生成效果基本描述模型描述程序设计参考资料 生成效果 基本描述 1.Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成&#xf…

揭秘动态内存管理,让你少走弯路!

1. 为什么要有动态内存分配 2. malloc和free 3. calloc和realloc 4. 常⻅的动态内存的错误 5. 动态内存经典笔试题分析 6. 柔性数组 7. 总结C/C中程序内存区域划分 正文开始&#xff1a; 1. 为什么要有动态内存分配 我们已经掌握的内存开辟⽅式有&#xff1a; int…

LeetCode---391周赛

题目列表 3099. 哈沙德数 3100. 换水问题 II 3101. 交替子数组计数 3102. 最小化曼哈顿距离 一、哈沙德数 简单的模拟题&#xff0c;代码如下 class Solution { public:int sumOfTheDigitsOfHarshadNumber(int x) {int s 0, tmp x;while(tmp){stmp%10;tmp/10;}return x…

Redis 5种数据结构常用命令

文章目录 1 字符串2 哈希3 列表4 集合5 有序集合 1 字符串 命令描述set key value设置指定key的值为valueget key获取指定key的值del key [key …]删除一个或多个keymset key value [key value …]设置多个key的值mget key [key …]获取一个或多个key的值incr key将key中储存的…

vue项目配置看板娘

这个博主讲的不错&#xff0c;很清楚&#xff0c;但是我实操时无法找到资源&#xff0c;一直报404找不到模型&#xff0c;苦恼了我很久也没解决&#xff0c;之后发现了 Evgo的项目&#xff0c;这就简单多了 最简单的引入Vue看板娘教程 一、项目引入 这里使用的是来自Evgo老哥…

03-JAVA设计模式-工厂模式详解

工厂模式 工厂设计模式是一种创建型设计模式&#xff0c;它提供了一种封装对象创建过程的机制&#xff0c;将对象的创建与使用分离。 这种设计模式允许我们在不修改客户端代码的情况下引入新的对象类型。 在Java中&#xff0c;工厂设计模式主要有三种形式&#xff1a;简单工厂…

每日OJ题_优先级队列_堆③_力扣692. 前K个高频单词

目录 力扣692. 前K个高频单词 解析代码 力扣692. 前K个高频单词 692. 前K个高频单词 难度 中等 给定一个单词列表 words 和一个整数 k &#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c…

潜水后可以戴耳机吗?精选四款防水游泳耳机,不惧水压挑战

随着生活水平的提高&#xff0c;人们越来越注重健康与休闲娱乐。潜水作为一项集运动、探险和乐趣于一身的活动&#xff0c;近年来受到了越来越多的关注。然而&#xff0c;在享受潜水带来的乐趣的同时&#xff0c;我们也希望能够在水下保持与外界的联系&#xff0c;例如欣赏音乐…

经济学 赋税

赋税&#xff1a; 1.为政府服务提供金钱来源 2. 用于保护环境 3.帮助国家使用财政和货币政策&#xff0c;推动经济增长 4.再分配社会财富的一种方式&#xff0c;平衡富人和穷人的贫富差距 5.帮助我们支付市场自身可能无法实现的服务&#xff0c;比如公共安全&#xff0c;国…

【MySQL】解决修改密码时报错:--skip-grant-tables option

首先我们先了解到为何会出现如上报错&#xff1a; 是因为我们在第一次配置MySQL中的my.cnf时&#xff0c;我们添加了–skip–grant-tables 选项 跳过验证身份的选项 所以&#xff0c;我们第一次登录成功后想要修改密码会出现如下报错&#xff1a; [hxiZ0jl69kyvg0h181cozuf5Z…

如何高效学习Python编程语言

理解Python的应用场景 不同的编程语言有不同的发展历史和应用场景,了解Python主要应用在哪些领域对于学习它会有很大帮助。Python最初是一种通用脚本语言,主要用于系统级任务自动化。随着时间的推移,它逐步成为数据处理、科学计算、Web开发、自动化运维等众多领域的主要编程语…

Vue - 3( 15000 字 Vue 入门级教程)

一&#xff1a;初识 Vue 1.1 收集表单数据 收集表单数据在Vue.js中是一个常见且重要的任务&#xff0c;它使得前端交互变得更加灵活和直观。 Vue中&#xff0c;我们通常使用v-model指令来实现表单元素与数据之间的双向绑定&#xff0c;从而实现数据的收集和更新。下面总结了…

深入浅出 -- 系统架构之负载均衡Nginx反向代理

一、Nginx反向代理-负载均衡 首先通过SpringBootFreemarker快速搭建一个WEB项目&#xff1a;springboot-web-nginx&#xff0c;然后在该项目中&#xff0c;创建一个IndexNginxController.java文件&#xff0c;逻辑如下&#xff1a; Controller public class IndexNginxControl…