WebApis知识总结以及案例(续3)

news2025/3/14 22:47:51

综合案例

小兔鲜页面注册

分析业务模块

  • 发送验证码模块

用户点击之后,显示05 秒后重新获取

时间到了,自动改为重新获取

    //1.发送短信验证码模块
    const code=document.querySelector('.code')
    let flag=true//通过一个变量来控制 节流阀 
    // 1.1 点击事件
    code.addEventListener('click',function(){
      if(flag){
        flag=false//时间未到点击之后不可触发事件
        let i=5
      // 点击完毕之后立马触发
      code.innerHTML=`0${i}秒后重新获取`

      let timerID=setInterval(function(){
        i--
        code.innerHTML=`0${i}秒后重新获取`
        if(i===0){
          clearInterval(timerID)
          flag=true//时间结束 点击之后可以触发事件
          // 重新获取
          code.innerHTML=`重新获取`
        }
      },1000)
      }
      
    })
  • 各个表单验证模块

用户名验证(注意封装函数 verifyxxx),失去焦点触发这个函数

  • 正则/^[a-zA-Z0-9-_]$/{6,16}
  • 如果不符合要求,则出现提示信息 并return false中断程序
  • 否则 则返回return true
  • 之所以返回布尔值 是为了最后的提交按钮做准备
  • 侦听使用change事件,当鼠标离开了表单,并且表单值发生了变化时触发(类似京东效果)
    const input =document.querySelector('input')
    input.addEventListener('change',function(){
      console.log(11);
    })
    // 2.验证用户名
    // 2.1获取用户名表单
    const username=document.querySelector('[name=username]')
    username.addEventListener('change',verfiyName)//函数名不加括号
    // 2.3封装vertifyName函数
    function verfiyName(){
      const span=username.nextElementSibling
      // console.log(11)
      // 2.4 定规则
      const reg=/^[a-zA-Z0-9-_]{6,16}$/
      if(!reg.test(username.value)){
        // console.log(11)
        span.innerText='输入不合法,请输入6~16位'
        return false
      }
      // 合法的 就清空span
      span.innerText=''
      return true
    }

手机号验证 

正则:/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/

其余同上

验证码验证

正则:/^\d{6}$/

其余同上

密码验证

正则:/^[a-zA-Z0-9-_]{6,20}$/

其余同上

再次密码验证

如果本次密码不等于上面输入的密码则返回错误信息

其余同上

我同意模块

添加类 .icon-queren2 则是默认选中样式,可以使用toggle切换类

表单提交模块

使用submit提交事件

  • 勾选已经阅读统一模块

如果没有勾选同意协议,则提示需要勾选

classList.contains()看看有没有包含某个类,如果有则返回true,没有则返回false

  • 下一步验证全部模块

只要上面有一个input验证不通过就不同意提交

如果上面input表单 只要有模块返回的是false 则阻止提交

    (function(){
      //1.发送短信验证码模块
    const code=document.querySelector('.code')
    let flag=true//通过一个变量来控制 节流阀 
    // 1.1 点击事件
    code.addEventListener('click',function(){
      if(flag){
        flag=false//时间未到点击之后不可触发事件
        let i=5
      // 点击完毕之后立马触发
      code.innerHTML=`0${i}秒后重新获取`

      let timerID=setInterval(function(){
        i--
        code.innerHTML=`0${i}秒后重新获取`
        if(i===0){
          clearInterval(timerID)
          flag=true//时间结束 点击之后可以触发事件
          // 重新获取
          code.innerHTML=`重新获取`
        }
      },1000)
      }
    })
    });
    
    // 2.验证用户名
    // 2.1获取用户名表单
    const username=document.querySelector('[name=username]')
    username.addEventListener('change',verfiyName)//函数名不加括号
    // 2.3封装vertifyName函数
    function verfiyName(){
      const span=username.nextElementSibling
      // console.log(11)
      // 2.4 定规则
      const reg=/^[a-zA-Z0-9-_]{6,16}$/
      if(!reg.test(username.value)){
        // console.log(11)
        span.innerText='输入不合法,请输入6~16位'
        return false
      }
      // 合法的 就清空span
      span.innerText=''
      return true
    }



    // 3.验证手机号
    // 2.1获取手机表单
    const phone=document.querySelector('[name=phone]')
    phone.addEventListener('change',verfiyPhone)//函数名不加括号
    // 2.3封装verfiyPhone函数
    function verfiyPhone(){
      const span=phone.nextElementSibling
      // console.log(11)
      // 2.4 定规则
      const reg=/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
      if(!reg.test(phone.value)){
        // console.log(11)
        span.innerText='输入不合法,请输入正确的手机号码'
        return false
      }
      // 合法的 就清空span
      span.innerText=''
      return true
    }



    // 4.验证验证码
    // 2.1获取验证码表单
    const code=document.querySelector('[name=code]')
    code.addEventListener('change',verfiyCode)//函数名不加括号
    // 2.3封装verfiycode函数
    function verfiyCode(){
      const span=code.nextElementSibling
      // console.log(11)
      // 2.4 定规则
      const reg=/^\d{6}$/
      if(!reg.test(code.value)){
        // console.log(11)
        span.innerText='输入不合法,请输入6位数字'
        return false
      }
      // 合法的 就清空span
      span.innerText=''
      return true
    }



    // 5.验证密码框
    // 2.1获取密码表单
    const password=document.querySelector('[name=password]')
    password.addEventListener('change',verfiypassword)//函数名不加括号
    // 2.3封装verfiypassword函数
    function verfiypassword(){
      const span=password.nextElementSibling
      // console.log(11)
      // 2.4 定规则
      const reg=/^[a-zA-Z0-9-_]{6,20}$/
      if(!reg.test(password.value)){
        // console.log(11)
        span.innerText='输入不合法,6~20位数字字母符号组成'
        return false
      }
      // 合法的 就清空span
      span.innerText=''
      return true
    }



    // 6.密码的再次验证
    // 2.1获取再次验证表单
    const confirm=document.querySelector('[name=confirm]')
    confirm.addEventListener('change',verfiyconfirm)//函数名不加括号
    // 2.3封装verfiyconfirm函数
    function verfiyconfirm(){
      const span=confirm.nextElementSibling
      // console.log(11)
      // 当前表单的值不等于密码框的值就是错误的
      if(confirm.value!==password.value){
        // console.log(11)
        span.innerText='两次密码输入不一致'
        return false
      }
      // 合法的 就清空span
      span.innerText=''
      return true
    }


    // 7.我同意
    const queren=document.querySelector('.icon-queren')
    queren.addEventListener('click',function(){
      // 原来有的就删掉 原来没有的就添加
      this.classList.toggle('icon-queren2')
    })



    // 8.提交模块
    const form=document.querySelector('form')
    form.addEventListener('submit',function(e){
      // 判断是否勾选我同意模块 如果有icon-queren2说明就勾选了 否则没勾选\
      if(!queren.classList.contains('icon-queren2')){
        e.preventDefault()
        return alert('请勾选同意协议')
      }
      //依次判断上面的每个input是否通过,只要有一个没通过就阻止
      if(!(verfiyName()&verfiyCode()&verfiyPhone()&verfiyconfirm()&verfiypassword())){
        e.preventDefault()
      }
    })

登录页

点击切换盒子

使用事件委托时,尽量不要在盒子套的很复杂的时候用,如果li标签里包了一个a元素,a元素里又包了个img元素,此时若给a标签设置事件委托,就不容易实现,因为点击的时候点击的是img元素。

    // tab栏切换
    const tab_nav=document.querySelector('.tab-nav')
    const pane=document.querySelectorAll('.tab-pane')
    // 1.1事件监听
    tab_nav.addEventListener('click',function(e){
      if(e.target.tagName==='A'){
        //取消上一active
        //当前元素添加active
        tab_nav.querySelector('.active').classList.remove('active')
        e.target.classList.add('active')
        for(let i=0;i<pane.length;i++){
          // 先干掉所有人 for循环
          pane[i].style.display='none'
        }
        // 让对应序号的大pane 显示
        pane[e.target.dataset.id].style.display='block'
      }
    })

点击登陆可以跳转页面

  • 先阻止默认行为
  • 如果没有勾选同意,则提示要勾选
  • required属性不能为空
  • 假设登陆成功
  • 把用户名记录到本地存储当中
  • 同时跳转首页 location.href
    // 点击提交模块
    const form=document.querySelector('form')
    const agree=document.querySelector('[name=agree]')
    const username=document.querySelector('[name=username]')
    form.addEventListener('submit',function(e){
      e.preventDefault()
      // 判断是否勾选同意协议
      if(!agree.checked){
        return alert('请勾选同意协议')
      }
      //记录用户名到本地存储
      localStorage.setItem('xtx-uname',username.value)
      // 跳转到首页
      location.href='./index.html'
    })

小兔鲜首页页面

步骤:

最好写个渲染函数,因为一会退出还要用到

1.如果本地存储有记录的用户名,读取本地存储数据

需要把用户名写到第一个li里面

格式:<a href="javascript:;"><i class="iconfont icon-user">用户名</i></a>

因为登陆了,所以第二个里面的文字变为:退出登录

格式:<a href="javascript:;">退出登录</a>

2.如果本地没有数据,则复原为默认的结构

3,点击退出登录,删除本地数据,并重新渲染函数

    // 1.获取第一个小li
    const li1=document.querySelector('.xtx_navs li:first-child')
    const li2=li1.nextElementSibling
    // 2.最好做个渲染函数 因为退出登录需要重新渲染
    function render(){
    // 2.1读取本地存储的用户名
    const uname=localStorage.getItem('xtx-uname')
    // console.log(uname)
    if(uname){
      li1.innerHTML=`<a href="javascript:;"><i class="iconfont icon-user">${uname}</i></a>`
      li2.innerHTML=`<a href="javascript:;">退出登录</a>`
    }else{
      li1.innerHTML='<a href="./login.html">请先登录</a>'
      li2.innerHTML='<a href="./register.html">免费注册</a>'
    }
}
render()
// 2.点击退出登录模块
li2.addEventListener('click',function(){
  //删除本地存储的数据
  localStorage.removeItem('xtx-uname')
  render()
})

放大镜效果

业务分析:

  • 鼠标经过对应小盒子,左侧中等盒子显示对应中等图片

1.获取对应的元素

2.采取事件委托的形式,监听鼠标经过小盒子里面扽图片,注意此时需要使用mouseover事件,因为需要事件冒泡触发small

3.让鼠标经过小图片,可以拿到小图片的src,可以做两件事

  • 让中等盒子的图片换成这个小图片的src
  • 让大盒子的背景图片,也换成这个小图片的src
    // 1. 获取三个盒子
    // 2. 小盒子 图片切换效果
    const small = document.querySelector('.small')
    //  中盒子
    const middle = document.querySelector('.middle')
    //  大盒子
    const large = document.querySelector('.large')
    // 2. 事件委托
    small.addEventListener('mouseover', function (e) {//事件冒泡
      if (e.target.tagName === 'IMG') {
        // console.log(111)
        // 排他 干掉以前的 active  li 上面
        this.querySelector('.active').classList.remove('active')
        // 当前元素的爸爸添加 active
        e.target.parentNode.classList.add('active')
        // 拿到当前小图片的 src
        // console.log(e.target.src)
        // 让中等盒子里面的图片,src 更换为   小图片src
        middle.querySelector('img').src = e.target.src
        // 大盒子更换背景图片
        large.style.backgroundImage = `url(${e.target.src})`
      }
    })
  • 鼠标经过中盒子,右侧会显示放大镜效果的大盒子

1.用到鼠标经过和i离开,鼠标经过中盒子,大盒子利用dislay来显示和隐藏

2,鼠标离开不会立马消失,而是有200ms的延迟,用户体验更好,所以尽量使用定时器做个延迟 settimeout

3.显示和隐藏也尽量定义一个函数,因为鼠标经过离开中等盒子,会显示隐藏,同时,鼠标经过大盒子,也会显示和隐藏

4,给大盒子里面的背景图片一个默认的第一张图片

 

    // 3. 鼠标经过中等盒子, 显示隐藏 大盒子
    middle.addEventListener('mouseenter', show)
    middle.addEventListener('mouseleave', hide)
    let timeId = null
    // 显示函数 显示大盒子
    function show() {
      // 先清除定时器
      clearTimeout(timeId)
      large.style.display = 'block'
    }
    // 隐藏函数 隐藏大盒子
    function hide() {
      timeId = setTimeout(function () {
        large.style.display = 'none'
      }, 200)
    }


    // 4. 鼠标经过大盒子, 显示隐藏 大盒子
    large.addEventListener('mouseenter', show)
    large.addEventListener('mouseleave', hide)
  • 黑色遮罩盒子跟着鼠标来移动
  1. 先做鼠标经过小盒子small盒子,显示隐藏黑色遮罩的盒子
  2. 让黑色遮罩跟着鼠标来走,需要用到鼠标移动事件 mousermove
  3. 让黑色盒子移动的核心思想:不断把鼠标在中等盒子内的坐标给遮罩层left top,这样遮罩层就可以跟着移动了

算法

  • 得到鼠标在页面中的坐标,利用事件对象的pageX
  • 得到中等盒子在页面中的坐标 middle.getBoundingClientRect()
  • 鼠标在中等盒子中的坐标=鼠标在页面中的坐标-middle中等盒子的坐标
  • 黑色遮罩层不断得到 鼠标在中等盒子中的坐标 就可以移动起来了
  • 注意y坐标特殊,需要减去页面被卷去的头部
  • 不用offsetLeft和offsetTop的原因:因为这两个属性跟带有定位的父级有关系,很容易被父级影响,而getBoundingClientRect()不受定位父元素的影响

限定遮罩的盒子只能在middle内部移动,需要添加判断

  • 限定水平方向 大于等于0并且小于等于400
  • 限定垂直方向大于等于0并且小于等于400

遮罩盒子移动的坐标:

  • 声明一个mx作为移动的距离
  • 水平坐标x如果小于等于100,则移动的距离mx就是0,不应该移动
  • 水平坐标如果大于等于100并且小于300,移动的距离就是mx-100(100)是遮罩层盒子自身宽度的一半
  • 水平坐标如果大于等于300,移动的距离就是mx=200不用再移动了
  • 其实水平移动就是在100~200之间移动的
  • 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置
    // 5. 鼠标经过中等盒子,显示隐藏 黑色遮罩层
    const layer = document.querySelector('.layer')
    middle.addEventListener('mouseenter', function () {
      layer.style.display = 'block'
    })
    middle.addEventListener('mouseleave', function () {
      layer.style.display = 'none'
    })
    // 6.移动黑色遮罩盒子
    middle.addEventListener('mousemove', function (e) {
      // let x = 10, y = 20
      // console.log(11)
      // 鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
      // console.log(e.pageX)鼠标在页面中的坐标
      // middle 中等盒子的坐标
      // console.log(middle.getBoundingClientRect().left)
      let x = e.pageX - middle.getBoundingClientRect().left
      let y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop//解决页面滚动时框下移的问题,减去被卷去的头部
      // console.log(x, y)
      // 黑色遮罩移动 在 middle 盒子内 限定移动的距离
      if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
        // 黑色盒子不是一直移动的
        // 声明2个变量 黑色盒子移动的 mx my变量 
        let mx = 0, my = 0
        if (x < 100) mx = 0
        if (x >= 100 && x <= 300) mx = x - 100
        if (x > 300) mx = 200

        if (y < 100) my = 0
        if (y >= 100 && y <= 300) my = y - 100
        if (y > 300) my = 200

        layer.style.left = mx + 'px'
        layer.style.top = my + 'px'
        // 大盒子的背景图片要跟随 中等盒子移动  存在的关系是 2倍   
        large.style.backgroundPositionX = -2 * mx + 'px'
        large.style.backgroundPositionY = -2 * my + 'px'
      }
    })

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[docker] 核心知识 - 概念和运行

[docker] 核心知识 - 概念和运行 之前 docker 学了个开头就去搞项目去了&#xff0c;不过项目也开展了好久了&#xff0c;前端差不多吃透了&#xff0c;有些新功能需要用 docker 和 k8s……是时候重新学习一下了。 这一部分简单的过一下概念和讲一下怎么运行 docker 镜像和启…

洛谷P1229 遍历问题

洛谷P1229 遍历问题 遍历问题 文章目录 遍历问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 正确代码 题目描述 我们都很熟悉二叉树的前序、中序、后序遍历&#xff0c;在数据结构中常提出这样的问题&#xff1a;已知一棵二叉树的前序和中序遍历&#xff0c;求它…

windows wireshark抓包rtmp推流出现TCP Retransmission

解决办法&#xff1a;tcp.port1935 && !(tcp.analysis.retransmission)

springcloud-fegin 组件调用

一、Feign 概述 Feign是Netflix开发的声明式、模板化的HTTP客户端&#xff0c; Feign可以帮助我们更快捷、优雅地调用HTTP API。 在Spring Cloud中&#xff0c;使用Feign非常简单——创建一个接口&#xff0c;并在接口上添加一些注解&#xff0c;代码就完成了。Feign支持多种…

武汉星起航:亚马逊跨境引领全球贸易新趋势,展现积极影响力

随着全球化浪潮的持续推进&#xff0c;跨境电商行业正迎来前所未有的发展机遇。亚马逊作为全球领先的电商平台&#xff0c;其在跨境电商领域的发展趋势备受瞩目。亚马逊跨境电商不仅扩大了跨境市场的规模&#xff0c;优化了供应链管理&#xff0c;还积极应用科技创新&#xff0…

硬件开源--Model 3C(简称M3)芯片驱动RGB接口86中控屏PCBA原理图

针对市场IOT应用需求&#xff0c;基于启明智显的Model3C芯片(简称M3)设计开发的一款超高性价比的86型中控屏PCBA原理图开源。 Model3C芯片(简称M3)是一款基于 RISC-V 的高性能、国产自主、工业级高清显示与智能控制 MCU&#xff0c;配备强大的 2D 图形加速处理器、PNG/JPEG 解码…

大话设计模式之访问者模式

访问者模式是一种行为设计模式&#xff0c;它允许你在不修改对象结构的前提下定义作用于这些对象结构元素的新操作。 在访问者模式中&#xff0c;有两个核心概念&#xff1a; 访问者&#xff08;Visitor&#xff09;&#xff1a;定义了对对象结构中每个元素的访问操作。每个访…

STM32的GPIO端口的八种模式解析

目录 STM32的GPIO端口的八种模式解析 一、上拉输入模式 二、下拉输入模式 三、浮空输入模式 四、模拟输入模式 五、推挽输出模式 六、开漏输出模式 七、复用推挽输出模式 八、复用开漏输出模式 STM32的GPIO端口的八种模式解析 在学习STM32的过程中&#xff0c;GPIO端口…

惨痛教训:我的专业赢得了辩论,却用情商丢掉了客户。

某一年&#xff0c;我给某市级部门做了一个3D展示的系统&#xff0c;时间紧&#xff0c;任务重&#xff0c;也是如期完成了。最后到市里去评审的时候&#xff0c;现场来了11个副主任&#xff0c;大家你一言我一语的对系统提出意见和建议。 那个时候我是年轻气盛&#xff0c;知道…

CPLD可运行的最高频率是多少

CPLD可运行的最高频率是多少 AG32 内置CPLD的可运行最高频率 AG32 内置CPLD的可运行最高频率 AG32 MCU 的运行最高频率是248M。而CPLD中没有标准的最高频率。 最大能跑多少MHz&#xff0c;取决于cpld 里的设计。 如果是逻辑电路&#xff0c;则不存在时钟的概念。 如果是时序电路…

无线测温技术在高炉炉壳温度检测中的应用/无线测温监控系统

安科瑞薛瑶瑶18701709087 摘要:应用方便灵活的无线测温和热成像技术对高炉炉壳进行检测&#xff0c;利用热成像进行检测&#xff0c;发现了温度异常区域后对关注部位进行点的检测&#xff0c;预防炉壳的烧穿&#xff0c;对温度数据采集及存储&#xff0c;通过查看历史趋势来对…

【Linux】进程的优先级环境变量

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. 进程的优先级2.1 什么是优先级2.2 为什么要有优先级2.3 优先级的查看方式2.4 对优先级调整 3. 命令行参数4. 环境变量4.1 环境变量与配置文件4.1.1 环境变量初步介绍4.1.2 配置文件 4.2 更多环境变量4.3 整…

HTTPS 加密解密大致流程

HTTPS简介 在我们开始配置之前&#xff0c;让我们先了解一下HTTPS和它的重要性。 为什么选择HTTPS&#xff1f; 加密传输&#xff1a;通过SSL/TLS协议&#xff0c;确保数据在传输过程中不被窃听。认证身份&#xff1a;确保客户端与预期的服务器通信&#xff0c;防止中间人攻…

密码学 | 椭圆曲线数字签名方法 ECDSA(下)

目录 10 ECDSA 算法 11 创建签名 12 验证签名 13 ECDSA 的安全性 14 随机 k 值的重要性 15 结语 ⚠️ 原文&#xff1a;Understanding How ECDSA Protects Your Data. ⚠️ 写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留着学习。同时&#xff0c;经过几…

00 【哈工大_操作系统】Bochs 汇编级调试方法及指令

本文将介绍一下哈工大李治军老师《操作系统》课程在完成Lab时所使用到的 Bochs 调试工具的使用方法。这是一款汇编级调试工具&#xff0c;打开调试模式非常简单&#xff0c;只需在终端下输入如下指令&#xff1a; 1、bochs 调试基本指令大全 功能指令举例在某物理地址设置断点…

LED电子显示屏的性能要求

LED电子显示屏作为一种重要的信息传播媒介&#xff0c;在各行各业得到广泛应用。然而&#xff0c;其性能要求直接影响到其稳定运行和有效传播信息的效果。以下是LED电子显示屏的性能要求概述&#xff1a; 1. 发光体可靠性 LED电子显示屏的发光体质量必须可靠稳定&#xff0c;保…

云安全与网络安全:有什么区别?

云计算已经存在了一段时间&#xff0c;但某些术语的正确含义仍然存在混乱。一个例子是区分云安全与网络安全。 首先&#xff0c;让我们看一下网络安全一词 &#xff0c;以了解它的含义。然后&#xff0c;我们将将该术语与云安全进行比较&#xff0c;以了解两者在几个关键领域的…

STM32笔记---CAN采样点设置和报错

STM32笔记---CAN采样点设置和报错 采样点设置再同步补偿宽度&#xff08;SJW&#xff09;设置 报错分析CAN中断使能寄存器CAN错误状态寄存器 采样点设置 以前配置CAN参数的BS1和BS2参数时认为总线波特率符合要求就可以了&#xff0c;其实同一个波特率可能对应多组参数设置的情…

vue3 el-table无表头

需要实现的样式 父组件 <template><div><!-- 表格组件 无表头 --><Table :label"tableData.label" :data"tableData.data" :querydata"tableData.querydata" :queryTitle"tableData.title"><template #o…

矩阵起源招聘进行时,寻找发光的你~

推荐有礼&#xff01;添加MO小助理 MO定制书包轻松GET~