目录

1. 小兔鲜注册页面验证

2. 阶段案例(登录、首页页面)(重点)

3. 小兔鲜放大镜效果

1. 小兔鲜注册页面验证

验证码模块有个小问题:

连续点击获取验证码会导致触发多次计时器,会导致计时出现问题,为了解决这个问题,可以设置一个变量来控制。如 flag = true  当触发点击事件时,首先判断 flag,为真则进入函数,否则不执行,进入函数后首先将 flag取反,然后当计时结束时,再设置 flag = true.

 侦听使用 change 事件,当鼠标离开了表单,并且表单值发生了变化时触发

对于同意模块使用的是小图标,而不是单选多选框,勾选的话应该为 i标签再添加一个类icon-queren2

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

  <script>// 使用立即执行函数,避免变量污染(function(){// 1.发送短信验证码模块const code = document.querySelector('.xtx-form a.code')let flag = true //通过一个变量来控制// 1.1 点击事件code.addEventListener('click', function(){if (flag) {// 取反了,不能马上第二次点击flag = falselet i = 5code.innerHTML = `0${i}s后重新获取`let timer = setInterval(function(){i--code.innerHTML = `0${i}s后重新获取`if (i === 0) {clearInterval(timer)code.innerHTML = `重新获取`// 到时间了,可以开启 flag了flag = true}        }, 1000)}})})();// 2. 验证用户名// 2.1 获取用户名表单const username = document.querySelector('.xtx-form [name=username]')// 2.2 使用change 事件  值发生变化的时候username.addEventListener('change', verifyName)// 2.3 封装函数function verifyName() {// console.log(00);const span =  username.nextElementSibling// 2.4 定规则 用户名const reg = /^[a-zA-Z0-9-_]{6,10}$/if (!reg.test(username.value)) {span.innerHTML = '用户名输入有误,请输入6~10位'return false}// 2.5 合法的   就清空 spanusername.nextElementSibling.innerHTML = ''return true}// 3. 验证手机号// 3.1 获取手机号表单const phone = document.querySelector('.xtx-form [name=phone]')// 3.2 使用change 事件  值发生变化的时候phone.addEventListener('change', verifyPhone)// 3.3 封装函数function verifyPhone() {// console.log(00);const span =  phone.nextElementSibling// 3.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)) {span.innerHTML = '输入有误,请输入正确的手机号'return false}// 3.5 合法的   就清空 spanphone.nextElementSibling.innerHTML = ''return true}// 4. 验证验证码// 4.1 获取验证码表单const code = document.querySelector('.xtx-form [name=code]')// 4.2 使用change 事件  值发生变化的时候code.addEventListener('change', verifyCode)// 4.3 封装函数function verifyCode() {// console.log(00);const span =  code.nextElementSibling// 4.4 定规则 验证码const reg = /^\d{6}$/if (!reg.test(code.value)) {span.innerHTML = '输入有误,请输入正确的验证码'return false}// 4.5 合法的   就清空 spancode.nextElementSibling.innerHTML = ''return true}// 5. 验证密码// 5.1 获取密码表单const password = document.querySelector('.xtx-form [name=password]')// 5.2 使用change 事件  值发生变化的时候password.addEventListener('change', verifyPassword)// 5.3 封装函数function verifyPassword() {// console.log(00);const span =  password.nextElementSibling// 5.4 定规则 密码const reg = /^[a-zA-Z0-9-_]{6,20}$/if (!reg.test(password.value)) {span.innerHTML = '输入有误,6~20位数字字母符号组成'return false}// 5.5 合法的   就清空 spanpassword.nextElementSibling.innerHTML = ''return true}// 6. 密码的再次验证// 6.1 获取再次验证密码表单const confirm = document.querySelector('.xtx-form [name=confirm]')// 6.2 使用change 事件  值发生变化的时候confirm.addEventListener('change', verifyConfirm)// 6.3 封装函数function verifyConfirm() {// console.log(00);const span =  confirm.nextElementSibling// 当前表单的值不等于密码框的值就是错误的if (confirm.value !== password.value) {span.innerHTML = '两次输入密码不一致'return false}// 6.4 合法的   就清空 spanconfirm.nextElementSibling.innerHTML = ''return true}// 7. 我同意模块const agree = document.querySelector('.xtx-form-item .icon-queren')agree.addEventListener('click', function(){// 切换类,原来有就删掉,原来没有就添加this.classList.toggle('icon-queren2')})// 8. 表单提交模块const form = document.querySelector('form')form.addEventListener('submit', function(e){// 判断是否勾选我同意模块,如果有 icon-queren2 说明就勾选了,否则就没勾选if(!agree.classList.contains('icon-queren2')) {alert('请勾选同意协议')// 阻止提交e.preventDefault()}// 依次判断上面的每个框框是否通过, 只要有一个没有通过的就阻止// console.log(verifyName());if (!verifyName()) e.preventDefault()if (!verifyPhone()) e.preventDefault()if (!verifyCode()) e.preventDefault()if (!verifyPassword()) e.preventDefault()if (!verifyConfirm()) e.preventDefault()})</script>

2. 阶段案例(登录、首页页面)(重点)

小兔鲜登录页面

tab栏切换时,由于对应的 .tab-pane两个盒子没有设置 active类,所以最好不要为其设置active类,不能使用排他思想,故可将所有的 .tab-pane获得,将其隐藏起来(for循环),然后再为对应的盒子设置显示。

h5新属性 required属性 表示不能为空

  <script>// 1.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') {// 排他思想,去掉上一个activetab_nav.querySelector('.active').classList.remove('active')// 当前元素添加activee.target.classList.add('active')// 先干掉所有人,for循环for(let i = 0; i < pane.length; i++) {pane[i].style.display = 'none'}// 让对应序号的 大pane显示pane[e.target.dataset.id].style.display = 'block'}})// 2. 点击登录跳转页面const form = document.querySelector('form')const agree = form.querySelector('[name=agree]')const username = form.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'})</script>

小兔鲜首页页面

注意在渲染的时候渲染的是小 li 而不是 a ,因为当显示用户名时会切换链接地址和添加小图标,同时对于第二个是退出登录还是请先注册的链接地址也不一样,故给 li 的innerHTML渲染。

  <script>// 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')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()})</script>

3. 小兔鲜放大镜效果

业务分析:

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

②: 鼠标经过中盒子,右侧会显示放大镜效果的大盒子

③: 黑色遮罩盒子跟着鼠标来移动

④: 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置

思路分析:

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

1. 获取对应的元素
2. 采取事件委托的形式,监听鼠标经过小盒子里面的图片, 注意此时需要使用 `mouseover` 事件,因为需要事件冒泡触发small,所以以后对于鼠标经过事件想用事件委托时使用 mouseover
3. 让鼠标经过小图片的爸爸li盒子,添加类,其余的li移除类(注意先移除,后添加)
4. 鼠标经过小图片,可以拿到小图片的src, 可以做两件事
   - 让中等盒子的图片换成这个 这个小图片的src
   - 让大盒子的背景图片,也换成这个小图片的 src (稍后做)

②: 鼠标经过中等盒子,右侧大盒子显示

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

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

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

4. 给大盒子里面的背景图片一个默认的第一张图片(去CSS样式中添加,因为在JS中写的大盒子背景是鼠标移入点击事件时把小盒子的图片地址给大盒子,但当页面一打开时,大盒子没有背景图片,此时移入中等盒子不会出现背景图片,有bug,所以我们应该给大盒子一个默认的第一张图片)

    function hide() {//  鼠标离开不会立马消失,而是有200ms的延时,使用setTimeout函数setTimeout(function(){large.style.display = 'none'}, 250)}

如果我们采用上面代码,会出现问题:鼠标一离开就开启一个定时器,所以当我们快速离开进入中等盒子时,会开启多个定时器,导致鼠标即使移入了中等盒子,但是由于定时器的隐藏效果会导致图片不显示。

因此,我们应该当鼠标进入中等盒子时,关掉定时器,采用如下写法:

    let timer = nullfunction show() {// 先清除定时器clearTimeout(timer)large.style.display = 'block'}// 隐藏函数 隐藏大盒子function hide() {//  鼠标离开不会立马消失,而是有200ms的延时,使用setTimeout函数timer = setTimeout(function(){large.style.display = 'none'}, 250)}

③: 黑色遮罩盒子跟着鼠标来移动

1.  先做鼠标经过 中等盒子,显示隐藏 黑色遮罩 的盒子

2.  让黑色遮罩跟着鼠标来走, 需要用到鼠标移动事件  mousemove  

3. 让黑色盒子的移动的核心思想:不断把鼠标在中等盒子内的坐标给黑色遮罩层 let  top 值,这样遮罩层就可以跟着移动了

- 需求

- 我们要的是 鼠标在 中等盒子内的坐标, 没有办法直接得到
     - 得到1:  鼠标在页面中的坐标
     - 得到2:  中等盒子在页面中的坐标

   - 算法

- 得到鼠标在页面中的坐标    利用事件对象的  pageX  
     - 得到middle中等盒子在页面中的坐标   middle.getBoundingClientRect()
     - 鼠标在middle 盒子里面的坐标   =   鼠标在页面中的坐标  -   middle 中等盒子的坐标
     - 黑色遮罩层不断得到       鼠标在middle 盒子中的坐标 就可以移动起来了

>注意 y坐标特殊,需要减去 页面被卷去的头部 ,因为getBoundingClientRect()获取的是相对于可视窗口的坐标,当页面滚动时,会出现问题
     >为什么不用 box.offsetLeft 和 box.offsetTop  因为这俩属性跟带有定位的父级有关系,很容被父级影响,而getBoundingClientRect() 不受定位的父元素的影响

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

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

通过console.log(middle.getBoundingClientRect());得到中等盒子的坐标如下图

  - 遮罩盒子移动的坐标:

- 声明一个 mx 作为移动的距离
     - 水平坐标 x 如果 小于等于100 ,则移动的距离 mx 就是  0  不应该移动
     - 水平坐标 如果 大于等于100 并且小于300,移动的距离 mx就是 x  - 100 (100是遮罩盒子自身宽度的一半)
     - 水平坐标 如果 大于等于300,移动的距离就是  mx   就是200  不应该在移动了
     - 其实我们发现水平移动, 就在 100 ~ 200 之间移动的
     - 垂直同理

        // 声明两个变量, 黑色盒子移动的距离let mx = 0let my = 0if (x <= 100) mx = 0if (x > 100 && x < 300) mx = x - 100if(x >= 300) mx = 200if (y <= 100) my = 0if (y > 100 && y < 300) my = y - 100if(y >= 300) my = 200

   - 大盒子图片移动的计算方法:
     - 中等盒子是 400px  大盒子 是 800px 的
     - 中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值

~~~JavaScript
   large.style.backgroundPositionX = - 2 * mx + 'px'
   large.style.backgroundPositionY = - 2 * my + 'px'

  <script>// 顶部导航栏自动滑出(function(){const sticky = document.querySelector('.sticky')const header = document.querySelector('.xtx_header .wrapper')const headerTop = header.offsetTopconst headerHeight = header.clientHeightconst top = headerTop + headerHeightwindow.addEventListener('scroll', function(){const n = document.documentElement.scrollTopif (n >= top) {sticky.style.top = '0px'} else {sticky.style.top = '-80px'}})})();// 三个盒子的故事,放大镜效果// 1. 获取三个盒子const small = document.querySelector('.small')const middle = document.querySelector('.middle')const large = document.querySelector('.large')// 2. 鼠标经过对应的小盒子,左侧中等盒子显示对应的图片// 事件委托,注意必须使用mouseover,因为事件委托利用的是冒泡原理,而mouseenter不能冒泡small.addEventListener('mouseover', function(e){if (e.target.tagName === 'IMG') {// 排他思想 干掉以前的 active  li 上面this.querySelector('.active').classList.remove('active')// 当前元素的爸爸li 添加 activee.target.parentNode.classList.add('active')// console.log(middle.children[0]);// 让中等盒子里面的图片,src 更换为   小图片srcmiddle.querySelector('img').src = e.target.src// 大盒子更换背景图片,注意图片背景的属性值为 url()large.style.backgroundImage = `url(${e.target.src})`}})// 3. 鼠标经过中等盒子,显示隐藏大盒子middle.addEventListener('mouseenter', show)middle.addEventListener('mouseleave', hide)// 显示函数 显示大盒子let timer = nullfunction show() {// 先清除定时器clearTimeout(timer)large.style.display = 'block'}// 隐藏函数 隐藏大盒子function hide() {//  鼠标离开不会立马消失,而是有200ms的延时,使用setTimeout函数timer = setTimeout(function(){large.style.display = 'none'}, 250)}// 4. 鼠标经过大盒子,显示隐藏大盒子large.addEventListener('mouseenter', show)large.addEventListener('mouseleave', hide)// 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){// 鼠标在中等盒子的坐标 = 鼠标在页面的坐标 - middle 盒子的坐标// console.log(middle.getBoundingClientRect().x);// console.log(middle.getBoundingClientRect().left);let x = e.pageX - middle.getBoundingClientRect().leftlet y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop// 黑色遮罩移动 在middle 盒子内 限定移动距离if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {// 黑色盒子不是一直移动的// 声明两个变量, 黑色盒子移动的距离let mx = 0let my = 0if (x <= 100) mx = 0if (x > 100 && x < 300) mx = x - 100if(x >= 300) mx = 200if (y <= 100) my = 0if (y > 100 && y < 300) my = y - 100if(y >= 300) my = 200layer.style.left = mx + 'px'layer.style.top = my + 'px'// 大盒子的背景图片要跟随 中等盒子移动 存在的关系是 2倍large.style.backgroundPositionX = -2 * mx + 'px'large.style.backgroundPositionY = -2 * my + 'px'}})//商品详情和商品评价切换const tabHead = document.querySelector('.tab-head')tabHead.addEventListener('click', function(e){if(e.target.tagName === 'A') {const active = document.querySelector('.tab-head .active')if (active) active.classList.remove('active')e.target.classList.add('active')const id = e.target.dataset.idconst a = id == 2 ? 3 : 2document.querySelector(`.main .cont>div:nth-child(${id})`).style.display = 'block'document.querySelector(`.main .cont>div:nth-child(${a})`).style.display = 'none'}})/* //点击尺寸(function () {const dd = document.querySelector('.item #size');dd.addEventListener('click', function (e) {if (e.target.tagName == 'SPAN') {const active = document.querySelector('.item #size .active');if (active) active.classList.remove('active');e.target.classList.add('active');}});})();//点击颜色(function () {const dd = document.querySelector('.item #color');dd.addEventListener('click', function (e) {if (e.target.tagName == 'IMG') {const active = document.querySelector('.item  #color img.active');if (active) active.classList.remove('active');e.target.classList.add('active');}});})(); */</script>

小兔鲜注册页面验证、阶段案例(登录、首页页面)(重点)、小兔鲜放大镜效果——DOM相关推荐

  1. 微信小程序-登陆注册滑块验证

    微信小程序-登陆注册滑块验证 一.创建自定义组件MoveVerify 二.在index页面使用 一.创建自定义组件MoveVerify MoveVerify.js Component({/*** 组件 ...

  2. 接收表单中的用户名和密码,如果用户名和密码分别为“admin“和“123456“,则返回登录成功页面,否则返回登录失败页面。

    接收表单中的用户名和密码,如果用户名和密码分别为"admin"和"123456",则返回登录成功页面,否则返回登录失败页面.已知登录面如下: <form ...

  3. ar 微信小程序_【看一看案例集】AR+微信小程序(1):认识篇

    去年,看一看科技"看看AR"."奇幻洛阳"等支持AR技术的小程序陆续上线.与此同时,不少商城也对"AR+小程序"产生浓厚的兴趣.但面对这么个 ...

  4. 小米6钉子户们的胜利!复刻机可能要来了,目前已在工程验证阶段

    小米6作为一代神机在米粉心目中的地位颇高,一大批"钉子户"仍在坚守阵地,上周雷军也为小米6提供电池换新服务,得到了米6用户的无数好评,足以见得该机有多么的厉害,在曾经开卖的阶段,一 ...

  5. 【微信小程序系列】微信小程序连接后端数据库(SSM)案例

    [微信小程序系列]微信小程序连接后端数据库(SSM)案例 登录页面 login.wxml <view class="page"><loading hidden=& ...

  6. asp.net mvc 自定义全局过滤器 验证用户是否登录

    一般具有用户模块的系统都需要对用户是否登录进行验证,如果用户登录了就可以继续操作,否则退回用户的登录页面 对于这样的需求我们可以通过自定义一个独立的方法来完成验证的操作,但是这样代码的重复率就大大提高 ...

  7. html怎样同框架页面内跳转,使用iframe框架时,实现子页面内跳转到整个页面,而不是在子页面内跳转...

    首先先来描述一下我所遇到的问题,我在一个首页的index.jsp页面中用到了iframe框架,见下图 在iframe中引入jsp页面的路径,是几个iframe框架组合成的一个完整的页面,但是他们的存在 ...

  8. 【JavaScript】小兔鲜登录页面(3)小兔鲜首页页面

    小兔鲜首页页面 需求: 从登录页面跳转过来之后,自动显示用户名 如果点击退出,则不显示用户名 步骤: 最好写个渲染函数,因为一会的退出,还需要用到 ①:如果本地存储有记录的用户名,读取本地存储数据   ...

  9. 小兔鲜项目-原生JS实现页面放大镜效果模块

    目录 1. 项目搭建 1.1 在项目开始之前,先做好准备工作,创建这样的文件目录 1.1.1 css文件夹 1.1.2 images文件 1.1.3 uploads文件 1.2 HTML结构 1.2. ...

最新文章

  1. 山东计算机类好的民办大学,山东四大坑人学校-山东坑人的民办大学(野鸡大学)...
  2. ubuntu16.04: mininet下使用ryu当做控制器
  3. Android NDK各版本下载
  4. linux 提取日志字段,记一次Linux下提取MySQL日志关键字段
  5. 【POJ - 2318】TOYS(计算几何,叉积判断点与直线位置关系,二分)
  6. hadoop集群服务重启后出错
  7. 圆圈1计算机语言,LOGO编程新理念  画圆和圆弧1★
  8. Excel怎么将两个表格数据合并为一个
  9. 【C语言刷题】汉诺塔问题
  10. 北大学霸隐居20年,王青松花光350万后,如今怎么样了?
  11. 4点策略教你如何做好社群营销
  12. 【Excel】给自己做个2020年高考倒计时
  13. 世界顶尖PHP站Facebook后台技术探秘
  14. 文件系统之软连接、硬链接的区别/文件删除与空间的联系/df和du的区别
  15. kubernetes 菜鸟_菜鸟系列k8s——k8s快速入门(1)
  16. OPNET计算机网络仿真 实验作业1 - 网络拓扑创建
  17. Linux入门和使用
  18. 淘宝网(关于淘宝拆分)
  19. 汇编语言之Debug教程篇
  20. AMA分享回顾丨镜像网络MW对于分布式存储底层系统的思考和后续发展的看法

热门文章

  1. 文件共享之SMB/CIFS协议及Samba的使用
  2. 平板电脑性价比排行榜新品新功能!看剧聊天还能这么玩?!
  3. JavaEE初阶系列 -开头篇:计算机是如何工作的(为下一篇的线程做铺垫)
  4. c语言横坐标加一怎么表示,在c语言里自动加一的函数怎么写
  5. java directui_win32 DirectUI控件开发与调用指南
  6. 快速掌握高清录屏方法?--QVE高清屏幕录制
  7. 2023年全国最新保安员精选真题及答案30
  8. 小白新手装机-----全
  9. C++和qt designer的混合编程--动态计算加法小工具
  10. Spark开发环境的搭建