Web APIs - 第6天笔记
目标:能够利用正则表达式完成小兔鲜注册页面的表单验证,具备常见的表单验证能力
- 正则表达式
- 综合案例
- 阶段案例
正则表达式
正则表达式(Regular Expression)是一种字符串匹配的模式(规则)
使用场景:
- 例如验证表单:手机号表单要求用户只能输入11位的数字 (匹配)
- 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等

正则基本使用
定义规则
const reg = /表达式/- 其中
/ /是正则表达式字面量 - 正则表达式也是
对象
- 其中
使用正则
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>
元字符
- 普通字符:
- 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。
- 普通字符只能够匹配字符串中与它们相同的字符。
- 比如,规定用户只能输入英文26个英文字母,普通字符的话 /[abcdefghijklmnopqrstuvwxyz]/
- 元字符(特殊字符)
- 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
- 比如,规定用户只能输入英文26个英文字母,换成元字符写法: /[a-z]/
参考文档:
边界符
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

如果 ^ 和 $ 在一起,表示必须是精确匹配
<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>
量词
量词用来设定某个模式重复次数

注意: 逗号左右两侧千万不要出现空格
<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>
范围
表示字符的范围,定义的规则限定在某个范围,比如只能是英文字母,或者数字等等,用表示范围

<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>
字符类
某些常见模式的简写方式,区分字母和数字


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

<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>
正则插件

change 事件
给input注册 change 事件,值被修改并且失去焦点后触发
// change 事件 内容发生了变化
const input = document.querySelector('input')
input.addEventListener('change', function () {
console.log(111)
})
判断是否有类

元素.classList.contains() 看看有没有包含某个类,如果有则返回true,么有则返回false
案例-小兔鲜页面注册

分析业务模块:
发送验证码模块
用户点击之后,显示 05秒后重新获取
时间到了,自动改为 重新获取

(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) } }) })();
各个表单验证模块
用户名验证(注意封装函数 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 }
勾选已经阅读同意模块
添加类 .icon-queren2 则是默认选中样式 可以使用 toggle切换类
// 7. 我同意 const queren = document.querySelector('.icon-queren') queren.addEventListener('click', function () { // 切换类 原来有的就删掉,原来没有就添加 this.classList.toggle('icon-queren2') })
下一步验证全部模块
使用 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)
案例-小兔鲜登录页面

案例需求分析
tab切换

// 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' } })
点击登录可以跳转页面
先阻止默认行为
如果没有勾选同意,则提示要勾选
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' })
从登录页面跳转过来之后,自动显示用户名
如果点击退出,则不显示用户名
// 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() })
