正则表达式

正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象,通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。

JavaScript中的使用场景

表单验证(匹配)
过滤敏感词(替换)
字符串中提取我们想要的部分(提取)

正则表达式语法分两步,一是定义规则,二是看是否匹配。

查找匹配字符串

test()方法 用于判断是否有符合规则的字符串,返回的是布尔值 找到返回true,否则false

exe()方法用于检索(查找)符合规则的字符串,找到返回数组,否则为null

// 正则表达式使用
const str = '我是来自河南洛阳,我叫霍欣标'
// 1. 定义规则
const reg = /霍欣标/

// 2. 是否匹配? test()用来查看正则表达式与指定的字符串是否匹配
console.log(reg.test(str)) // true 或 false

// 3. 检索(查找)符合规则的字符串 exec()
console.log(reg.exec(str)) // 返回数组 或 null(未知)

元字符

大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。

而元字符是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。

MDN文档:正则表达式 在线正则表达式测试

元字符分类

边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)
量词(表示重复次数)
字符类(\d表示0~9

边界符

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

console.log(/哈/.test('哈'))  // true
console.log(/哈/.test('哈哈')) // true
console.log(/哈/.test('二哈'))  // true

// 边界符
// 1. 以哈开头
console.log(/^哈/.test('哈')) // true
console.log(/^哈/.test('二哈')) //false

// 2. 以哈开头
console.log(/^哈$/.test('哈'))  // true
// 精确匹配,以哈结尾,只能有一个哈
console.log(/^哈$/.test('哈哈')) //false

量词

量词用来设定某个模式出现的次数。注意:逗号左右两侧千万不要出现空格

// 量词 * 类似 >= 0次
console.log(/^哈$/.test('哈')) // true
console.log(/^哈*$/.test('哈')) // true
console.log(/^哈*$/.test('哈哈')) // true
console.log(/^哈*$/.test('哈很啥')) // false
console.log(/^哈*$/.test('哈很傻')) // false

// 量词 + 类似 >= 1次
console.log(/^哈$/.test('哈')) // true
console.log(/^哈+$/.test('')) // false
console.log(/^哈+$/.test('哈')) // true
console.log(/^哈+$/.test('哈哈')) // true
console.log(/^哈+$/.test('二哈很傻')) // false
console.log(/^哈+$/.test('哈很啥')) // false

// 量词 ? 类似 0或1次
console.log(/^哈?$/.test('')) // true
console.log(/^哈?$/.test('哈')) // true
console.log(/^哈?$/.test('哈哈')) // false
console.log(/^哈?$/.test('二哈很傻')) // false
console.log(/^哈?$/.test('哈很啥')) // false

// 量词{n} 写几,必须出现几次
console.log(/^哈{4}$/.test('哈'))      //false
console.log(/^哈{4}$/.test('哈哈'))    //false
console.log(/^哈{4}$/.test('哈哈哈哈')) // true
console.log(/^哈{4}$/.test('哈哈哈哈哈')) // false
console.log(/^哈{4}$/.test('哈哈哈哈哈哈')) // false

// 量词{n,}  >=n 
console.log(/^哈{4,}$/.test('哈'))      //false
console.log(/^哈{4,}$/.test('哈哈'))    //false
console.log(/^哈{4,}$/.test('哈哈哈哈')) // true
console.log(/^哈{4,}$/.test('哈哈哈哈哈')) // true
console.log(/^哈{4,}$/.test('哈哈哈哈哈哈')) // true

// 量词{n,m}  >=n 并且 <=m 逗号左右两侧于万不能有空格
console.log(/^哈{4,6}$/.test('哈'))      //false
console.log(/^哈{4,6}$/.test('哈哈'))    //false
console.log(/^哈{4,6}$/.test('哈哈哈哈')) // true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈')) // true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈')) // true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈')) // true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈哈')) // false

字符类

[]是匹配字符集合,后面的字符串只要包含abc中任意一个字符,都返回true

// 字符类 [abc] 只能选一个
console.log(/^[abc]$/.test('a')) // true
console.log(/^[abc]$/.test('b')) // true
console.log(/^[abc]$/.test('c')) // true
console.log(/^[abc]$/.test('ab')) // false
console.log(/^[abc]{2}$/.test('ab')) // true
console.log(/^[a-z]$/.test('p')) // true
console.log(/^[A-Z]$/.test('p')) // false
console.log(/^[0-9]$/.test('3')) // true
console.log(/^[a-zA-Z0-9]$/.test('3')) // true
console.log(/^[a-zA-Z0-9]$/.test('L')) // true
console.log(/^[a-zA-Z0-9]{4,8}$/.test('L123abCB')) // true

// QQ号从10000开始,{重复次数}是重复最近那个[1-9]
console.log(/^[1-9][0-9]{4,}$/.test('19696000')) // true
console.log(/^[^a-zA-Z0-9]$/.test('12ac')) // false
console.log(/^[^a-zA-Z0-9]$/.test('耷')) // true

预定类

预定义指的是 某些常见模式的简写方式。

预定类说明
\d匹配0-9之间的任一数字,相当于[0-9]
\D匹配所有0-9以外的字符,相当于[^0-9]
\w匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
\W除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
\s匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f]
\S匹配非空格的字符,相当于[^\t\r\n\v\f]

案例:用户名验证案例

用户名要求用户英文字母,数字,下划线或者短横线组成,并且用户名长度为6~16位。 Demo

分析:

① 首先准备好这种正则表达式模式/^[a-ZA-Z0-9-_]{6,16}$/
② 当表单失去焦点就开始验证
③ 如果符合正则规范,则让后面的span标签添加right
④ 如果不符合正则规范,则让后面的span标签添加wrong

// 正则表达式 [-_]中特殊符号要写在最后面
const reg = /^[a-zA-Z0-9-_]{6,16}$/
const input = document.querySelector('input')
const span = input.nextElementSibling

// 表单失去光标事件
input.addEventListener('blur', function () {
  if (reg.test(this.value)) {
    span.innerHTML = '输入正确'
    span.classList.add('right')
    span.className = 'right'
  } else {
    span.innerHTML = '请输入6~16位英文数字下划线'
    span.classList.add('error')
  }
})

修饰符

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

console.log(/^java$/.test('java')) // true
console.log(/^java$/.test('JAVA')) // false
console.log(/^java$/i.test('JAVA')) // true
console.log(/^java$/i.test('Java')) // true

replace替换

console.log(/^java$/.test('java')) // true
console.log(/^java$/.test('JAVA')) // false
console.log(/^java$/i.test('JAVA')) // true
console.log(/^java$/i.test('Java')) // true


// g是全局替换,不然只能替换一个,i是匹配不区分大小写
const str = 'java是一门编程语言, 学完java工资很高'
const result = str.replace(/java/gi, '前端')
// const result = str.replace(/java|JAVA/g, '前端')
console.log(result)
// 前端是一门编程语言, 学完前端工资很高

案例:过滤敏感字

需求:要求用户不能输入敏感字 Demo

分析:

① 用户输入内容
② 内容进行正则替换查找,找到敏感词,进行**
③ 要全局替换使用修饰符g

const tx = document.querySelector('textarea')
const btn = document.querySelector('button')
const div = document.querySelector('div')

btn.addEventListener('click', function () {
  // console.log(tx.value)
  div.innerHTML = tx.value.replace(/激情|基情/g, '**')
  tx.value = ''
})

综合案例

案例:小兔鲜页面注册

分析业务模块:Demo

① 发送验证码模块

  • 用户点击之后,显示 05秒后重新获取,时间到了,自动改为重新获取

② 各个表单验证模块,(注意封装函数verifyxxx),失去焦点触发这个函数

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

③ 勾选已经阅读同意模块

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

④ 下一步验证全部模块:使用submit提交事件

  • 只要上面有一个input验证不通过就不同意提交
  • 如果没有勾选同意协议,则提示 需要勾选
  • classList.contains()看看有没有包含某个类,如果有则返回true,么有则返回false
  • 如果上面input表单 只要有模块,返回的是false则阻止提交
// 模块一  发送验证码
// 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 = true
      }
    }, 1000)
  }
})

// 模块二  各个表单验证
// 1. 获取用户表单
const username = document.querySelector('[name=username]')
// 1.1 使用change事件
username.addEventListener('change', verifyName)
// 1.2 封装函数 verifyName
function verifyName() {
  const span = username.nextElementSibling
  // 1.3 定规则
  const reg = /^[a-zA-Z0-9-_]{6,10}$/
  // 1.4 账号表单输入不等于reg,则取反false执行下面的代码
  if (!reg.test(username.value)) {
    span.innerHTML = '输入不合法,请输入6~10位'
    // 返回错误的结果 是不合法的
    return false  // 中断程序
  }
  // 1.5 合法就清空
  span.innerHTML = ''
  return true
}

// 模块三  验证手机号
// 1. 获取用户表单
const phone = document.querySelector('[name=phone]')
// 1.1 使用change事件
phone.addEventListener('change', verifyPhone)
// 1.2 封装函数 verifyName
function verifyPhone() {
  const span = phone.nextElementSibling
  // 1.3 定规则
  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}$/
  // 1.4 账号表单输入不等于reg,则取反false执行下面的代码
  if (!reg.test(phone.value)) {
    span.innerHTML = '输入不合法,请输入正确的11位手机号'
    // 返回错误的结果 是不合法的
    return false  // 中断程序
  }
  // 1.5 合法就清空
  span.innerHTML = ''
  return true
}

// 模块四  验证验证码
// 1. 获取用户表单
const codeInput = document.querySelector('[name=code]')
// 1.1 使用change事件
codeInput.addEventListener('change', verifyCode)
// 1.2 封装函数 verifyName
function verifyCode() {
  const span = codeInput.nextElementSibling
  // 1.3 定规则
  const reg = /^\d{6}$/
  // 1.4 账号表单输入不等于reg,则取反false执行下面的代码
  if (!reg.test(codeInput.value)) {
    span.innerHTML = '输入不合法,请输入6位数字'
    // 返回错误的结果 是不合法的
    return false  // 中断程序
  }
  // 1.5 合法就清空
  span.innerHTML = ''
  return true
}

// 模块五  验证密码
// 1. 获取用户表单
const password = document.querySelector('[name=password]')
// 1.1 使用change事件
password.addEventListener('change', verifyPassword)
// 1.2 封装函数 verifyName
function verifyPassword() {
  const span = password.nextElementSibling
  // 1.3 定规则
  const reg = /^[a-zA-Z0-9-_]{6,20}$/
  // 1.4 账号表单输入不等于reg,则取反false执行下面的代码
  if (!reg.test(password.value)) {
    span.innerHTML = '输入不合法,请输入6~20数字字母组成'
    // 返回错误的结果 是不合法的
    return false  // 中断程序
  }
  // 1.5 合法就清空
  span.innerHTML = ''
  return true
}

// 模块六  密码的再次验证
// 1. 获取用户表单
const confirm = document.querySelector('[name=confirm]')
// 1.1 使用change事件
confirm.addEventListener('change', verifyConfirm)
// 1.2 封装函数 verifyName
function verifyConfirm() {
  const span = password.nextElementSibling
  // 1.4 账号表单输入不等于reg,则取反false执行下面的代码
  if (confirm.value !== password.value) {
    span.innerHTML = '两次密码输入不一致'
    // 返回错误的结果 是不合法的
    return false  // 中断程序
  }
  // 1.5 合法就清空
  span.innerHTML = ''
  return true
}

// 模块七  我同意模块
const queren = document.querySelector('.icon-queren')
queren.addEventListener('click', function () {
  // 切换类,原来有就删除,原来没有就添加
  this.classList.toggle('icon-queren2')
})

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

案例:小兔鲜登录页面

模块一 tab切换 Demo

模块二 点击登录可以跳转页面

  1. 先阻止默认行为
  2. 如果没有勾选同意,则提示要勾选
  3. required属性不能空
  4. 假设登录成功
    • 把用户名记录到本地存储中
    • 同时跳转到首页location.href
// 1. tab栏切换  事件委托
const tab_nav = document.querySelector('.tab-nav')
const pane = document.querySelectorAll('.tab-pane')
const username = document.querySelector('[name=username]')

// 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 (let i = 0; i < pane.length; i++)
      pane[i].style.display = 'none'
  }
  // 让对应序号的大盒子显示
  pane[e.target.dataset.id].style.display = 'block'
})

// 点击提交模块
const form = document.querySelector('form')
const agree = document.querySelector('[name=agree]')
form.addEventListener('submit', function (e) {
  e.preventDefault()
  // 判断是否勾选了复选框同意协议
  if (!agree.checked) {
    return alert('请勾选同意')
  }
  // 记录用户名到本地存储
  localStorage.setItem('xtx-uname', username.value)
  // 跳转到首页
  location.href = './index.html'
})

案例:小兔鲜首页页面

第一,从登录页面跳转过来之后,自动显示用户名;Demo

第二,如果点击退出,则不显示用户名

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

  1. 如果本地存储有记录的用户名,读取本地存储数据
    • 需要把用户名写到第一个li里面
    • 因为登录了,所以第二个里面的文字变为退出登录
  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()
})

原创文章,作者:霍欣标,如若转载,请注明出处:https://www.bigengwu.cn/xue/139.html

霍欣标的头像霍欣标
上一篇 2024-08-26 03:44
下一篇 2024-09-05 13:46

相关推荐

博主人懒,应管局要求暂不开启站内私信和评论功能,如需帮助请发邮件。

邮箱账号:1969600480@qq.com