正则表达式(语法、元字符(边界符、量词、字符类)、修饰符)、PC端网页特效(offset、client、scroll、动画系列)、案例:放大镜效果

目录

1、作用及使用场景

2、语法

1)定义语法

2)判断是否有符合规则的字符串

3)检索(查找)符合规则的字符串

3、元字符

1)好处

2)分类

(1)边界符

(2)量词

(3)字符类

a.[ ]匹配字符集合

b.[ ]里面加上 - 连字符

c. [ ]里面加上 ^ 取反符号

d.预定义

4、案例:验证用户名

5、修饰符

案例:过滤敏感词

6、案例

1)注册页面

2)登录页面

3)首页制作

7、PC端网页特效

1)元素偏移量offset系列

2)元素可视区client系列

3)元素滚动scroll系列

4)三大系列总结

5)动画函数封装

(1)动画函数

(2)缓动效果原理

(3)动画函数添加回调函数

8、案例:放大镜效果

1、作用及使用场景

2、语法

        步骤:定义规则+查找

1)定义语法

2)判断是否有符合规则的字符串

  <script>
    const str = 'abcdefghijklmn'
    const reg = /fgh/
    console.log(reg.test(str)); // true
  </script>
3)检索(查找)符合规则的字符串

3、元字符

1)好处

2)分类

(1)边界符

  <script>
    console.log(/^a/.test('a')); // true
    console.log(/^a/.test('aa')); // true
    console.log(/^a/.test('ab')); // true
    console.log(/^a/.test('b')); // false
    console.log(/^a$/.test('a')); // true 只有这种情况为 true
    console.log(/^a$/.test('aa')); // false
    console.log('-------------------');

  </script>
(2)量词

        用来设定某个模式出现的次数

  <script>
    console.log(/^a$/.test('a')); // true 只有这种情况为 true
    // * >=0次为 true
    console.log(/^a*$/.test('aa')); // true
    console.log(/^a*$/.test('')); // true
    console.log(/^a*$/.test('ab')); // false
    console.log(/^a*$/.test('b')); // false
    console.log(/^a*$/.test(' ')); // false
    console.log('-------------------');
    // + >0次为 true
    console.log(/^a+$/.test('aa')); // true
    console.log(/^a+$/.test('')); // false
    console.log(/^a+$/.test('ab')); // false
    console.log(/^a+$/.test('b')); // false
    console.log(/^a+$/.test(' ')); // false
    console.log('-------------------');
    // ? 0 || 1 次为 true
    console.log(/^a?$/.test('a')); // true
    console.log(/^a?$/.test('aa')); // false
    console.log(/^a?$/.test('')); // true
    console.log(/^a?$/.test('ab')); // false
    console.log(/^a?$/.test('b')); // false
    console.log(/^a?$/.test(' ')); // false
    console.log('-------------------');
    // {n} n为几就出现几次
    console.log(/^a{3}$/.test('')); // false
    console.log(/^a{3}$/.test('a')); // false
    console.log(/^a{3}$/.test('aa')); // false
    console.log(/^a{3}$/.test('aaa')); // true
    console.log(/^a{3}$/.test('aaaa')); // false
    console.log(/^a{3}$/.test('aaaaa')); // false
    console.log('-------------------');
    // {n,} >=n次
    console.log(/^a{3,}$/.test('')); // false
    console.log(/^a{3,}$/.test('a')); // false
    console.log(/^a{3,}$/.test('aa')); // false
    console.log(/^a{3,}$/.test('aaa')); // true
    console.log(/^a{3,}$/.test('aaaa')); // true
    console.log(/^a{3,}$/.test('aaaaa')); // true
    console.log('-------------------');
    // {n,m} n~m次 逗号左右不能有空格
    console.log(/^a{2,4}$/.test('')); // false
    console.log(/^a{2,4}$/.test('a')); // false
    console.log(/^a{2,4}$/.test('aa')); // true
    console.log(/^a{2,4}$/.test('aaa')); // true
    console.log(/^a{2,4}$/.test('aaaa')); // true
    console.log(/^a{2,4}$/.test('aaaaa')); // false
  </script>
(3)字符类
a.[ ]匹配字符集合

b.[ ]里面加上 - 连字符

c. [ ]里面加上 ^ 取反符号

d.预定义

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

4、案例:验证用户名

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    span {
      display: inline-block;
      width: 250px;
      height: 30px;
      vertical-align: middle;
      line-height: 30px;
      padding-left: 15px;
    }

    .error {
      color: red;
      background: url(/images/error1.png) no-repeat left center;
    }

    .right {
      color: green;
      background: url(/images/right.png) no-repeat left center;
    }
  </style>
</head>

<body>
  <input type="text">
  <span></span>
  <script>
    const reg = /^[a-zA-Z0-9-_]{6,16}$/
    const input = document.querySelector('input')
    const span = document.querySelector('span')
    input.addEventListener('blur', function () {
      if (reg.test(this.value)) {
        span.innerHTML = '输入正确'
        // className 会覆盖类名
        span.className = 'right'
      } else {
        span.innerHTML = '请输入6~16位的英文数字下划线'
        span.className = 'error'
      }
    })
  </script>
</body>

</html>

5、修饰符

案例:过滤敏感词

<body>
  <textarea name="" id="" cols="30" rows="10"></textarea>
  <button>发布</button>
  <div></div>
  <script>
    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 = ''
    })
  </script>
</body>

6、案例

1)注册页面

  <script>
    (function () {
      //  发送短信验证码模块
      const code = document.querySelector('.code')
      let flag = true  // 通过一个变量来控制   节流阀 
      //  点击事件
      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)
        }
      })
    })();

    //  验证用户名
    const username = document.querySelector('[name=username]')
    //  使用change事件  值发生变化的时候
    username.addEventListener('change', verifyName)
    //  封装verifyName函数
    function verifyName() {
      const span = username.nextElementSibling
      // 定规则  用户名
      const reg = /^[a-zA-Z0-9-_]{6,10}$/
      if (!reg.test(username.value)) {
        span.innerText = '输入不合法,请输入6~10位'
        return false
      }
      // 合法 就清空span
      span.innerText = ''
      return true
    }

    //  获取手机表单
    const phone = document.querySelector('[name=phone]')
    //  使用change事件  值发生变化的时候
    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)) { // !取反
        // console.log(11)
        span.innerText = '输入不合法,请输入正确的11位手机号码'
        return false
      }
      //  合法 就清空span
      span.innerText = ''
      return true
    }

    // 获取验证码表单
    const codeInput = document.querySelector('[name=code]')
    // 使用change事件  值发生变化的时候
    codeInput.addEventListener('change', verifyCode)
    function verifyCode() {
      const span = codeInput.nextElementSibling
      //  定规则  
      const reg = /^\d{6}$/
      if (!reg.test(codeInput.value)) {
        span.innerText = '输入不合法,6 位数字'
        return false
      }
      // 4.5 合法就清空span
      span.innerText = ''
      return true
    }

    //  验证密码框
    const password = document.querySelector('[name=password]')
    // 使用change事件  值发生变化的时候
    password.addEventListener('change', verifyPwd)
    function verifyPwd() {
      const span = password.nextElementSibling
      //  定规则 
      const reg = /^[a-zA-Z0-9-_]{6,20}$/
      if (!reg.test(password.value)) {
        span.innerText = '输入不合法,6~20位数字字母符号组成'
        return false
      }
      //  合法 就清空span
      span.innerText = ''
      return true
    }

    //  密码再次验证
    const confirm = document.querySelector('[name=confirm]')
    confirm.addEventListener('change', verifyConfirm)
    function verifyConfirm() {
      const span = confirm.nextElementSibling
      //  当前表单的值不等于 密码框的值就是错误的
      if (confirm.value !== password.value) {
        // console.log(11)
        span.innerText = '两次密码输入不一致'
        return false
      }
      // 6.5 合法 就清空span
      span.innerText = ''
      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) {
      // 判断是否勾选我同意模块 ,如果有 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()
    })
  </script>
2)登录页面
  <script>
    // 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') {
        // 取消上一个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'
      }
    })

    // 点击提交模块
    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'
    })
  </script>
3)首页制作
  <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')
      // 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>

7、PC端网页特效

1)元素偏移量offset系列

注意:offset以带有定位的父亲为准,如果没有父亲或者父亲没有定位,则以body为准

        parentNode返回的是最近一级的父亲,不管父亲有没有定位;offsetParent返回带有定位的父亲,否则返回body。

与style的区别:

2)元素可视区client系列

3)元素滚动scroll系列

4)三大系列总结

5)动画函数封装
(1)动画函数

核心原理:通过定时器setInterval()不断移动盒子位置

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div {
      position: absolute;
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }
  </style>
</head>

<body>
  <div></div>
  <script>
    function movLeft(obj, target) {
      clearInterval(obj.timerId)
      obj.timerId = setInterval(function () {
        if (obj.offsetLeft > target) clearInterval(obj.timerId)
        obj.style.left = obj.offsetLeft + 1 + 'px'
      }, 20)
    }
    const div = document.querySelector('div')
    movLeft(div, 500)
  </script>
</body>

</html>
(2)缓动效果原理

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    div {
      position: absolute;
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }

    span {
      position: absolute;
      top: 200px;
      width: 100px;
      height: 100px;
      background-color: pink;
    }

    button {
      width: 100px;
      height: 30px;
      background-color: #fff;
    }
  </style>
</head>

<body>
  <!-- <div></div> -->
  <span></span>
  <button class="btn500">点击到500</button>
  <button class="btn1000">点击到1000</button>
  <script>
    function movLeft(obj, target) {
      clearInterval(obj.timerId)
      obj.timerId = setInterval(function () {
        // 缓动动画公式:(目标值 - 当前位置) / 10 + 'px'
        // 把步长值改为整数
        let step = ((target - obj.offsetLeft) / 10)
        step = step > 0 ? Math.ceil(step) : Math.floor(step)
        if (obj.offsetLeft === target) clearInterval(obj.timerId)
        obj.style.left = obj.offsetLeft + step + 'px'
      }, 15)
    }
    const div = document.querySelector('div')
    const span = document.querySelector('span')
    const btn500 = document.querySelector('.btn500')
    const btn1000 = document.querySelector('.btn1000')
    // movLeft(div, 1000)
    btn500.addEventListener('click', function () {
      movLeft(span, 500)
    })
    btn1000.addEventListener('click', function () {
      movLeft(span, 1000)
    })
  </script>
</body>

</html>
(3)动画函数添加回调函数

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    div {
      position: absolute;
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }

    span {
      position: absolute;
      top: 200px;
      width: 100px;
      height: 100px;
      background-color: pink;
    }

    button {
      width: 100px;
      height: 30px;
      background-color: #fff;
    }
  </style>
</head>

<body>
  <!-- <div></div> -->
  <span></span>
  <button class="btn500">点击到500</button>
  <button class="btn1000">点击到1000</button>
  <script>
    function movLeft(obj, target, callback) {
      clearInterval(obj.timerId)
      obj.timerId = setInterval(function () {
        // 缓动动画公式:(目标值 - 当前位置) / 10 + 'px'
        // 把步长值改为整数
        let step = ((target - obj.offsetLeft) / 10)
        step = step > 0 ? Math.ceil(step) : Math.floor(step)
        if (obj.offsetLeft === target) {
          clearInterval(obj.timerId)
          if (callback) callback()
        }
        obj.style.left = obj.offsetLeft + step + 'px'
      }, 15)
    }
    const div = document.querySelector('div')
    const span = document.querySelector('span')
    const btn500 = document.querySelector('.btn500')
    const btn1000 = document.querySelector('.btn1000')
    // movLeft(div, 1000)
    btn500.addEventListener('click', function () {
      movLeft(span, 500)
    })
    btn1000.addEventListener('click', function () {
      movLeft(span, 1000, function () {
        // alert('!!!')
        span.style.backgroundColor = 'blue'
      })
    })
  </script>
</body>

</html>

8、案例:放大镜效果

  <script>

    //顶部导航栏自动滑出
    (function () {
      const sticky = document.querySelector('.sticky');
      const header = document.querySelector('.xtx_header .wrapper');
      const headerTop = header.offsetTop;
      const heaerHeight = header.clientHeight;
      const top = headerTop + heaerHeight;
      window.addEventListener('scroll', function () {
        const n = document.documentElement.scrollTop;
        if (n >= top) {
          sticky.style.top = '0px';
        } else {
          sticky.style.top = '-80px';
        }
      })
    })();

    // 放大镜效果
    (function () {
      //  获取三个盒子
      //  小盒子 图片切换效果
      const small = document.querySelector('.small')
      //  中盒子
      const middle = document.querySelector('.middle')
      //  大盒子 放大镜
      const large = document.querySelector('.large')
      //  采取事件委托形式,监听鼠标经过小盒子里面的图片,要使用mouseover事件,因为需要事件冒泡触发small
      // mouseover 有冒泡,相反mouseenter没有冒泡
      small.addEventListener('mouseover', function (e) {
        // console.log(e.target.tagName)
        if (e.target.tagName === 'IMG') {
          // 排他 干掉以前的 active  li 上面
          this.querySelector('.active').classList.remove('active')
          // 当前元素的父级添加 active
          e.target.parentNode.classList.add('active')
          // 拿到当前小图片的 src
          // console.log(e.target.src)
          // 让中等盒子里面图片的src 更换为小图片的src
          middle.querySelector('img').src = e.target.src
          // 大盒子更换背景图片
          large.style.backgroundImage = `url(${e.target.src})`
        }
      })


      //  鼠标经过中等盒子, 显示隐藏 大盒子
      middle.addEventListener('mouseenter', show)
      middle.addEventListener('mouseleave', hide)
      let timeId = null
      // 显示函数 显示大盒子
      function show() {
        // 先清除定时器 
        clearTimeout(timeId)
        large.style.display = 'block'
      }
      // 隐藏函数 隐藏大盒子
      function hide() {
        timeId = setTimeout(function () {
          large.style.display = 'none'
        }, 200)
      }


      // 鼠标经过大盒子, 显示隐藏 大盒子
      large.addEventListener('mouseenter', show)
      large.addEventListener('mouseleave', hide)

      // 鼠标经过中等盒子,显示隐藏 黑色遮罩层
      const layer = document.querySelector('.layer')
      middle.addEventListener('mouseenter', function () {
        layer.style.display = 'block'
      })
      middle.addEventListener('mouseleave', function () {
        layer.style.display = 'none'
      })
      // 移动黑色遮罩盒子
      middle.addEventListener('mousemove', function (e) {
        // let x = 10, y = 20
        // console.log(11)
        // 鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
        // console.log(e.pageX)鼠标在页面中的坐标
        // middle 中等盒子的坐标
        // console.log(middle.getBoundingClientRect().left)
        let x = e.pageX - middle.getBoundingClientRect().left
        let y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop
        // console.log(x, y)
        // 黑色遮罩移动 在 middle 盒子内 限定移动的距离
        if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
          // 黑色盒子不是一直移动的
          // 声明2个变量 黑色盒子移动的 mx my变量 
          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'
          // 大盒子的背景图片要跟随 中等盒子移动  存在的关系是 2倍   
          large.style.backgroundPositionX = -2 * mx + 'px'
          large.style.backgroundPositionY = -2 * my + 'px'
        }
      })
    })();


    //商品详情和商品评价切换
    (function () {
      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.id;
          const a = id == 2 ? 3 : 2;
          document.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>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值