Web APIs - 第6天笔记

目标:能够利用正则表达式完成小兔鲜注册页面的表单验证,具备常见的表单验证能力

  • 正则表达式
  • 综合案例
  • 阶段案例

正则表达式

正则表达式(Regular Expression)是一种字符串匹配的模式(规则)

使用场景:

  • 例如验证表单:手机号表单要求用户只能输入11位的数字 (匹配)
  • 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等

67607966636

正则基本使用

  1. 定义规则

    const reg =  /表达式/
    
    • 其中/ /是正则表达式字面量
    • 正则表达式也是对象
  2. 使用正则

    • test()方法 用来查看正则表达式与指定的字符串是否匹配
    • 如果正则表达式与指定的字符串匹配 ,返回true,否则false
<body>
  <script>
    // 正则表达式的基本使用
    const str = 'web前端开发'
    // 1. 定义规则
    const reg = /web/

    // 2. 使用正则  test()
    console.log(reg.test(str))  // true  如果符合规则匹配上则返回true
    console.log(reg.test('java开发'))  // false  如果不符合规则匹配上则返回 false
  </script>
</body>

元字符

  1. 普通字符:
  • 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。
  • 普通字符只能够匹配字符串中与它们相同的字符。
  • 比如,规定用户只能输入英文26个英文字母,普通字符的话 /[abcdefghijklmnopqrstuvwxyz]/
  1. 元字符(特殊字符)
  • 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
  • 比如,规定用户只能输入英文26个英文字母,换成元字符写法: /[a-z]/

参考文档:

边界符

正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

67608008165

如果 ^ 和 $ 在一起,表示必须是精确匹配

<body>
  <script>
    // 元字符之边界符
    // 1. 匹配开头的位置 ^
    const reg = /^web/
    console.log(reg.test('web前端'))  // true
    console.log(reg.test('前端web'))  // false
    console.log(reg.test('前端web学习'))  // false
    console.log(reg.test('we'))  // false

    // 2. 匹配结束的位置 $
    const reg1 = /web$/
    console.log(reg1.test('web前端'))  //  false
    console.log(reg1.test('前端web'))  // true
    console.log(reg1.test('前端web学习'))  // false
    console.log(reg1.test('we'))  // false  

    // 3. 精确匹配 ^ $
    const reg2 = /^web$/
    console.log(reg2.test('web前端'))  //  false
    console.log(reg2.test('前端web'))  // false
    console.log(reg2.test('前端web学习'))  // false
    console.log(reg2.test('we'))  // false 
    console.log(reg2.test('web'))  // true
    console.log(reg2.test('webweb'))  // flase 
  </script>
</body>

量词

量词用来设定某个模式重复次数

67608018538

注意: 逗号左右两侧千万不要出现空格

<body>
  <script>
    // 元字符之量词
    // 1. * 重复次数 >= 0 次
    const reg1 = /^w*$/
    console.log(reg1.test(''))  // true
    console.log(reg1.test('w'))  // true
    console.log(reg1.test('ww'))  // true
    console.log('-----------------------')

    // 2. + 重复次数 >= 1 次
    const reg2 = /^w+$/
    console.log(reg2.test(''))  // false
    console.log(reg2.test('w'))  // true
    console.log(reg2.test('ww'))  // true
    console.log('-----------------------')

    // 3. ? 重复次数  0 || 1 
    const reg3 = /^w?$/
    console.log(reg3.test(''))  // true
    console.log(reg3.test('w'))  // true
    console.log(reg3.test('ww'))  // false
    console.log('-----------------------')


    // 4. {n} 重复 n 次
    const reg4 = /^w{3}$/
    console.log(reg4.test(''))  // false
    console.log(reg4.test('w'))  // flase
    console.log(reg4.test('ww'))  // false
    console.log(reg4.test('www'))  // true
    console.log(reg4.test('wwww'))  // false
    console.log('-----------------------')

    // 5. {n,} 重复次数 >= n 
    const reg5 = /^w{2,}$/
    console.log(reg5.test(''))  // false
    console.log(reg5.test('w'))  // false
    console.log(reg5.test('ww'))  // true
    console.log(reg5.test('www'))  // true
    console.log('-----------------------')

    // 6. {n,m}   n =< 重复次数 <= m
    const reg6 = /^w{2,4}$/
    console.log(reg6.test('w'))  // false
    console.log(reg6.test('ww'))  // true
    console.log(reg6.test('www'))  // true
    console.log(reg6.test('wwww'))  // true
    console.log(reg6.test('wwwww'))  // false

    // 7. 注意事项: 逗号两侧千万不要加空格否则会匹配失败

  </script>

范围

表示字符的范围,定义的规则限定在某个范围,比如只能是英文字母,或者数字等等,用表示范围

67608029616

<body>
  <script>
    // 元字符之范围  []  
    // 1. [abc] 匹配包含的单个字符, 多选1
    const reg1 = /^[abc]$/
    console.log(reg1.test('a'))  // true
    console.log(reg1.test('b'))  // true
    console.log(reg1.test('c'))  // true
    console.log(reg1.test('d'))  // false
    console.log(reg1.test('ab'))  // false

    // 2. [a-z] 连字符 单个
    const reg2 = /^[a-z]$/
    console.log(reg2.test('a'))  // true
    console.log(reg2.test('p'))  // true
    console.log(reg2.test('0'))  // false
    console.log(reg2.test('A'))  // false
    // 想要包含小写字母,大写字母 ,数字
    const reg3 = /^[a-zA-Z0-9]$/
    console.log(reg3.test('B'))  // true
    console.log(reg3.test('b'))  // true
    console.log(reg3.test(9))  // true
    console.log(reg3.test(','))  // flase

    // 用户名可以输入英文字母,数字,可以加下划线,要求 6~16位
    const reg4 = /^[a-zA-Z0-9_]{6,16}$/
    console.log(reg4.test('abcd1'))  // false 
    console.log(reg4.test('abcd12'))  // true
    console.log(reg4.test('ABcd12'))  // true
    console.log(reg4.test('ABcd12_'))  // true

    // 3. [^a-z] 取反符
    const reg5 = /^[^a-z]$/
    console.log(reg5.test('a'))  // false 
    console.log(reg5.test('A'))  // true
    console.log(reg5.test(8))  // true

  </script>
</body>

字符类

某些常见模式的简写方式,区分字母和数字

67608035363

67608037232

替换和修饰符

replace 替换方法,可以完成字符的替换

67608043716

<body>
  <script>
    // 替换和修饰符
    const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'
    // 1. 替换  replace  需求:把前端替换为 web
    // 1.1 replace 返回值是替换完毕的字符串
    // const strEnd = str.replace(/前端/, 'web') 只能替换一个
  </script>
</body>

修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等

  • i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
  • g 是单词 global 的缩写,匹配所有满足正则表达式的结果
<body>
  <script>
    // 替换和修饰符
    const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'
    // 1. 替换  replace  需求:把前端替换为 web
    // 1.1 replace 返回值是替换完毕的字符串
    // const strEnd = str.replace(/前端/, 'web') 只能替换一个

    // 2. 修饰符 g 全部替换
    const strEnd = str.replace(/前端/g, 'web')
    console.log(strEnd) 
  </script>
</body>

正则插件

67608054863

change 事件

给input注册 change 事件,值被修改并且失去焦点后触发

// change 事件 内容发生了变化
const input = document.querySelector('input')
input.addEventListener('change', function () {
  console.log(111)
})

判断是否有类

67608061879

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

案例-小兔鲜页面注册

image-20240206103852766

分析业务模块:

  1. 发送验证码模块

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

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

      image-20240206104105327
    • (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)
                    // 从新获取
                    code.innerHTML = `重新获取`
                    // 到时间了,可以开启 flag了
                    flag = true
                  }
                }, 1000)
              }
            })
          })();
      
  2. 各个表单验证模块

    • 用户名验证(注意封装函数 verifyxxx) , 失去焦点触发这个函数。正则 /^[a-zA-Z0-9-_]{6,10}$/

    • 如果不符合要求,则出现提示信息 并 return false 中断程序,否则,则返回return true 之所以返回 布尔值,是为了 最后的提交按钮做准备,侦听使用change事件,当鼠标离开了表单,并且表单值发生了变化时触发(类似京东效果)

    • 手机号验证/^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}$/

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

    • // 2. 验证的是用户名
      // 2.1 获取用户名表单
      const username = document.querySelector('[name=username]')
      // 2.2 使用change事件  值发生变化的时候
      username.addEventListener('change', verifyName)
      // 2.3 封装verifyName函数
      function verifyName() {
        // console.log(11)
        const span = username.nextElementSibling
        // 2.4 定规则  用户名
        const reg = /^[a-zA-Z0-9-_]{6,10}$/
        if (!reg.test(username.value)) {
          // console.log(11)
          span.innerText = '输入不合法,请输入6~10位'
          return false
        }
        // 2.5 合法的 就清空span
        span.innerText = ''
        return true
      }
      
  3. 勾选已经阅读同意模块

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

    • // 7. 我同意
      const queren = document.querySelector('.icon-queren')
      queren.addEventListener('click', function () {
        // 切换类  原来有的就删掉,原来没有就添加
        this.classList.toggle('icon-queren2')
      })
      
  4. 下一步验证全部模块

    • 使用 submit 提交事件

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

    • 是否同意通过,classList.contains() 看看有没有包含某个类,如果有则返回true,么有则返回false

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

    • // 8. 提交模块
      const form = document.querySelector('form')
      form.addEventListener('submit', function (e) {
        // 判断是否勾选我同意模块 ,如果有 icon-queren2说明就勾选了,否则没勾选
        if (!queren.classList.contains('icon-queren2')) {
          alert('请勾选同意协议')
          // 阻止提交
          e.preventDefault()
        }
        // 依次判断上面的每个框框 是否通过,只要有一个没有通过的就阻止
        // console.log(verifyName())
        if (!verifyName()) e.preventDefault()
        if (!verifyPhone()) e.preventDefault()
        if (!verifyCode()) e.preventDefault()
        if (!verifyPwd()) e.preventDefault()
        if (!verifyConfirm()) e.preventDefault()
      })
      

[小兔鲜注册全部代码](https://gitee.com/web-workspacex/02JavaScript/tree/master/web APIs第六天/04-code/综合案例素材/register.html)

案例-小兔鲜登录页面

image-20240206110306401

案例需求分析

  1. tab切换

    image-20240206110915999
    • // 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') {
              // 取消上一个active
              tab_nav.querySelector('.active').classList.remove('active')
              // 当前元素添加active
              e.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. 点击登录可以跳转页面

    • 先阻止默认行为

    • 如果没有勾选同意,则提示要勾选

    • required 属性不能为空

      <!-- required:表示此项是必填的-->
      <input required type="text" placeholder="请输入用户名称/手机号码" name="username">
      
    • 假设登录成功

    • 把用户名记录到本地存储中

    • 同时跳转到首页 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'
          })
      
  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()  // 调用函数
      
  4. 点击 退出登录

    • 删除本地存储对应的用户名数据

    • 重新调用渲染函数即可

    • // 2. 点击退出登录模块
      li2.addEventListener('click', function () {
        // 删除本地存储的数据
        localStorage.removeItem('xtx-uname')
        // 重新渲染
        render()
      })
      

[小兔鲜登陆全部代码](https://gitee.com/web-workspacex/02JavaScript/tree/master/web APIs第六天/04-code/综合案例素材/login.html)

Loading...