【WEB APIs】正则表达式
目录
1. 正则表达式
1.1 介绍
1.2 语法编辑
1.3 元字符
1.3.1 边界符
1.3.2 量词
1.3.3 字符类
1.4 修饰符
2. 小兔鲜页面注册
3. 小兔鲜登陆页面
login
index
4. 小兔鲜图片切换+放大镜
1. 正则表达式
1.1 介绍
1.2 语法
const str = '前端啦啦啦啦啦啦lllll'
// 1.定义规则
const reg = /前端/
// 2.是否匹配
console.log((reg.test(str))) //true
1.3 元字符
1.3.1 边界符
1.3.2 量词
console.log((/^哈$/.test('哈哈'))) //只有一个字符且是哈,其余情况都是false
console.log((/^哈*$/.test('哈是哈'))) //false,不允许出现除'哈'外的其他字符,哈的数量>=0都为true
console.log((/^哈+$/.test(''))) //false,不允许出现除'哈'外的其他字符,哈的数量>=1都为true
console.log((/^哈?$/.test('哈哈'))) //false,不允许出现除'哈'外的其他字符,哈的数量=0/1时返回true
console.log((/^哈{4}$/.test('哈哈'))) // 只有'哈哈哈哈'是true
console.log((/^哈{4,}$/.test('哈哈'))) // 哈的数量>=4时是true
console.log((/^哈{4,6}$/.test('哈哈'))) // 6>=哈的数量>=4时是true
1.3.3 字符类
console.log((/^[abc]$/.test('ab'))) // [abc]只能有一个,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('2'))) // true
console.log((/^[a-zA-Z0-9]$/.test('2'))) // true
console.log((/^[a-zA-Z0-9]$/.test('P'))) // true
案例—用户名验证
<script>
const input = document.querySelector('input')
const span = input.nextElementSibling
const reg = /^[a-zA-Z0-9-_]{6,16}$/
input.addEventListener('blur', function () {
if (reg.test(this.value)) {
span.innerHTML = '输入正确'
span.className = 'right' //不用加.
} else {
span.innerHTML = '输入错误'
span.className = 'error' //className会覆盖类
}
})
</script>
1.4 修饰符
过滤敏感词
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 = ''
})
2. 小兔鲜页面注册
<script>
// 1.发送短信验证码
(function () {
const code = document.querySelector('.code')
let flag = true
code.addEventListener('click', function () {
if (flag) { //时间没到不能重复点击
flag = false
let i = 5 //防止1秒的空白
code.innerHTML = `0${i}秒后重新获取`
let timerId = setInterval(function () {
i--
code.innerHTML = `0${i}秒后重新获取`
if (i === 0) {
clearInterval(timerId)
code.innerHTML = `重新获取`
}
flag = true
}, 1000)
}
})
})();
// 2.验证用户名
const username = document.querySelector('[name=username]')
// 使用change事件,值发生变化的时候触发
username.addEventListener('change', verifyName)
// 封装verifyName函数
function verifyName() {
// console.log(1);
const span = username.nextElementSibling
const reg = /^[a-zA-Z0-9-_]{6,10}$/ //定义用户名的规则
if (!reg.test(username.value)) {
span.innerHTML = '输入不合法,请输入6~10位'
return false //中断程序(退出函数)
}
span.innerHTML = ''
return true
}
// 3.验证手机号
const phone = document.querySelector('[name=phone]')
phone.addEventListener('change', verifyPhone)
function verifyPhone() {
const span = phone.nextElementSibling
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 = '输入不合法,请输入11位手机号'
return false //中断程序(退出函数)
}
span.innerHTML = ''
return true
}
// 4.验证验证码
const code = document.querySelector('[name=code]')
code.addEventListener('change', verifyCode)
function verifyCode() {
const span = code.nextElementSibling
const reg = /^\d{6}$/ //定义用户名的规则
if (!reg.test(code.value)) {
span.innerHTML = '输入不合法,请输入6位验证码'
return false //中断程序(退出函数)
}
span.innerHTML = ''
return true
}
// 5.验证密码
const password = document.querySelector('[name=password]')
password.addEventListener('change', verifyPassword)
function verifyPassword() {
const span = password.nextElementSibling
const reg = /^[a-zA-Z0-9-_]{6,20}$/ //定义用户名的规则
if (!reg.test(password.value)) {
span.innerHTML = '输入不合法,请输入6~20位数字/字母/符号'
return false //中断程序(退出函数)
}
span.innerHTML = ''
return true
}
// 6.再次验证密码
const confirm = document.querySelector('[name=confirm]')
confirm.addEventListener('change', verifyConfirm)
function verifyConfirm() {
const span = confirm.nextElementSibling
if (confirm.value !== password.value) {
span.innerHTML = '两次密码输入不一致'
return false //中断程序(退出函数)
}
span.innerHTML = ''
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) {
if (!queren.classList.contains('icon-queren2')) {
alert('请勾选同意协议')
e.preventDefault() //阻止提交
}
//依次判断各个输入框是否通过,只要一个未通过就不提交
if (!verifyName() || !verifyPhone() || !verifyCode() || !verifyPassword() || !verifyConfirm()) e.preventDefault()
})
</script>
3. 小兔鲜登陆页面
login
<script>
// 1.tab栏切换 事件委托
const tab_nav = document.querySelector('.tab-nav')
const pane = document.querySelectorAll('.tab-pane')
tab_nav.addEventListener('click', function (e) {
if (e.target.tagName === 'A') {
tab_nav.querySelector('.active').classList.remove('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'
}
})
// 2.点击提交
const form = document.querySelector('form')
const agree = document.querySelector('[name=agree]')
const username = document.querySelector('[name=username]')
const password = document.querySelector('[name=password]')
form.addEventListener('submit', function (e) {
e.preventDefault()
if (!agree.checked) {
return alert('请勾选同意协议')
}
//记录用户名到本地存储
// localStorage.setItem('xtx-uname', username.value)
localStorage.setItem(`${username.value}`, password.value)
//跳转到首页
location.href = './index.html'
})
</script>
index
<script>
const li1 = document.querySelector('.xtx_navs li:first-child')
const li2 = li1.nextElementSibling
// 退出登录需要重新渲染,所以最好做个渲染函数
function render() {
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()
// 退出登录模块
li2.addEventListener('click', function () {
localStorage.removeItem('xtx-uname')
render() //重新渲染
})
</script>
4. 小兔鲜图片切换+放大镜
黑色遮罩盒子跟着鼠标来移动
-
先做鼠标经过 中等盒子,显示隐藏 黑色遮罩 的盒子
-
让黑色遮罩跟着鼠标来走, 需要用到鼠标移动事件 mousemove
-
让黑色盒子的移动的核心思想:不断把鼠标在中等盒子内的坐标给黑色遮罩层 let top 值,这样遮罩层就可以跟着移动了
-
需求
-
我们要的是 鼠标在 中等盒子内的坐标, 没有办法直接得到
-
得到1: 鼠标在页面中的坐标
-
得到2: 中等盒子在页面中的坐标
-
-
算法
-
得到鼠标在页面中的坐标 利用事件对象的 pageX
-
得到middle中等盒子在页面中的坐标 middle.getBoundingClientRect()
-
鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
-
黑色遮罩层不断得到 鼠标在middle 盒子中的坐标 就可以移动起来了
注意 y坐标特殊,需要减去 页面被卷去的头部
为什么不用 box.offsetLet 和 box.offsetTop 因为这俩属性跟带有定位的父级有关系,很容被父级影响,而getBoundingClientRect() 不受定位的父元素的影响
-
-
限定遮罩的盒子只能在middle 内部移动,需要添加判断
-
限定水平方向 大于等于0 并且小于等于 400
-
限定垂直方向 大于等于0 并且小于等于 400
-
-
遮罩盒子移动的坐标:
-
声明一个 mx 作为移动的距离
-
水平坐标 x 如果 小于等于100 ,则移动的距离 mx 就是 0 不应该移动
-
水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100 (100是遮罩盒子自身宽度的一半)
-
水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
-
其实我们发现水平移动, 就在 100 ~ 200 之间移动的
-
垂直同理
-
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
-
大盒子图片移动的计算方法:
-
中等盒子是 400px 大盒子 是 800px 的图片
-
中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值
-
large.style.backgroundPositionX = - 2 * mx + 'px' large.style.backgroundPositionY = - 2 * my + 'px'
-
<script>
const small = document.querySelector('.small')
const middle = document.querySelector('.middle')
const large = document.querySelector('.large')
// 1.鼠标经过小盒子,tab栏切换
// mouseenter 没有冒泡,事件委托用不了,要用mouseover
small.addEventListener('mouseover', function (e) {
if (e.target.tagName === 'IMG') {
this.querySelector('.active').classList.remove('active')
e.target.parentNode.classList.add('active')
middle.querySelector('img').src = e.target.src //将中等盒子里面的图片地址换成小盒子里的
large.style.backgroundImage = `url(${e.target.src})`
}
})
// 2.鼠标经过中等盒子,放大镜效果
middle.addEventListener('mouseenter', show)
middle.addEventListener('mouseleave', hide)
let timeId = 0 //只要有一个定时器工作就行,防止频繁触发无法显示大图
function show() {
clearTimeout(timeId) //先清除定时器
large.style.display = 'block'
}
function hide() {
//延迟0.2秒隐藏
timeId = setTimeout(function () {
large.style.display = 'none'
}, 200)
}
// 3.鼠标经过大盒子显示,离开隐藏
large.addEventListener('mouseenter', show)
large.addEventListener('mouseleave', hide)
// 4.鼠标经过中等盒子,显示隐藏遮罩盒子
const layer = document.querySelector('.layer')
middle.addEventListener('mouseenter', function () {
layer.style.display = 'block'
})
middle.addEventListener('mouseleave', function () {
layer.style.display = 'none'
})
// 5.移动黑色遮罩盒子
middle.addEventListener('mousemove', function (e) {
//鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
let x = e.pageX - middle.getBoundingClientRect().left
let y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop
// console.log(x, y);
if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
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'
// 大盒子的背景图片跟随黑色遮罩层移动,移动方向相反,关系是两倍
large.style.backgroundPositionX = -2 * mx + 'px'
large.style.backgroundPositionY = -2 * my + 'px'
}
})
</script>