47.[前端开发-JavaScript高级]Day12-Storage存储-正则表达式-认识防抖

发布于:2025-05-01 ⋅ 阅读:(14) ⋅ 点赞:(0)

Storage、正则表达式

1 LocalStorage

认识Storage

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // storage基本使用
    // 1.token的操作
    let token = localStorage.getItem("token")
    if (!token) {
      console.log("从服务器获取token")
      token = "coderwhytokeninfo"
      localStorage.setItem("token", token)
    }

    // 2.username/password的操作
    let username = localStorage.getItem("username")
    let password = localStorage.getItem("password")
    if (!username || !password) {
      console.log("让用户输入账号和密码")
      username = "coderwhy"
      password = "123456"
      // 将token/username/password保存到storage
      localStorage.setItem("username", username)
      localStorage.setItem("password", password)
    }

    // 3.后续的操作
    console.log(token)
    console.log(token.length)
    console.log(token + " 哈哈哈")

  </script>

</body>
</html>

2 SessionStorage

localStorage和sessionStorage的区别

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <a href="./static/about.html" target="_blank">关于</a>

  <script>

    // 1.验证一: 关闭网页
    // 1.1.localStorage的存储保持
    // localStorage.setItem("name", "localStorage")

    // 1.2.sessionStorage的存储会消失
    // sessionStorage.setItem("name", "sessionStorage")


    // 2.验证二: 打开新的网页
    // localStorage.setItem("info", "local")
    // sessionStorage.setItem("info", "session")

    
    // 3.验证三: 打开新的页面, 并且是在新的标签中打开
    localStorage.setItem("infoTab", "local")
    sessionStorage.setItem("infoTab", "session")

  </script>

</body>
</html>

Storage常见的方法和属性

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    const ACCESS_TOKEN = "token"

    console.log(localStorage.length)
    // 常见的方法:
    localStorage.setItem(ACCESS_TOKEN, "whytoken")
    console.log(localStorage.getItem(ACCESS_TOKEN))

    // 其他方法
    console.log(localStorage.key(0))
    console.log(localStorage.key(1))
    console.log(localStorage.removeItem("infoTab"))
    localStorage.clear()

  </script>

</body>
</html>

工具封装

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script src="./js/cache.js"></script>
  <script>

    localCache.setCache("sno", 111)

    // storage本身是不能直接存储对象类型的
    const userInfo = {
      name: "why",
      nickname: "coderwhy",
      level: 100,
      imgURL: "http://github.com/coderwhy.png"
    }

    // localStorage.setItem("userInfo", JSON.stringify(userInfo))
    // console.log(JSON.parse(localStorage.getItem("userInfo")))

    sessionCache.setCache("userInfo", userInfo)
    console.log(sessionCache.getCache("userInfo"))

  </script>

</body>
</html>

3 正则表达式的使用

什么是正则表达式?

正则表达式的使用方法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 创建正则
    const re1 = /abc/ig

    const message = "fdabc123 faBC323 dfABC222 A2324aaBc"

    // 1.使用正则对象上的实例方法


    // 2.使用字符串的方法, 传入一个正则表达式
    // 需求: 将所有的abc(忽略大小写)换成cba
    // const newMessage = message.replaceAll("abc", "cba")
    // console.log(newMessage)
    
    const newMessage = message.replaceAll(/abc/ig, "cba")
    console.log(newMessage)

    // 需求: 将字符串中数字全部删除
    const newMessage2 = message.replaceAll(/\d+/ig, "")
    console.log(newMessage2)


  </script>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  输入账号: <input type="text">
  <p class="tip">请输入账号</p>
  
  <script>

    // 创建正则
    const re1 = /abc/ig
    const message = "fdabc123 faBC323 dfABC222 A2324aaBc"

    // 1.使用正则对象上的实例方法
    // webpack -> loader -> test: 匹配文件名
    // 正则 -> 拿到文件 -> loader操作
    // 1.1.test方法: 检测某一个字符串是否符合正则的规则
    // if (re1.test(message)) {
    //   console.log("message符合规则")
    // } else {
    //   console.log("message不符合规则")
    // }

    // 1.2.exec方法: 使用正则执行一个字符串
    // const res1 = re1.exec(message)
    // console.log(res1)


    // 2.使用字符串的方法, 传入一个正则表达式
    // 2.1. match方法:
    // const result2 = message.match(re1)
    // console.log(result2)

    // 2.2. matchAll方法
    // 注意: matchAll传入的正则修饰符必须加g
    // const result3 = message.matchAll(re1)
    // // console.log(result3.next())
    // // console.log(result3.next())
    // // console.log(result3.next())
    // // console.log(result3.next())
    // for (const item of result3) {
    //   console.log(item)
    // }

    // 2.3. replace/replaceAll方法

    // 2.4. split方法
    // const result4 = message.split(re1)
    // console.log(result4)

    // 2.5. search方法
    const result5 = message.search(re1)
    console.log(result5)


    // 案例: 让用户输入的账号必须是aaaaa以上
    // const inputEl = document.querySelector("input")
    // const tipEl = document.querySelector(".tip")

    // inputEl.oninput = function() {
    //   const value = this.value
    //   if (/^a{5,8}$/.test(value)) {
    //     tipEl.textContent = "输入的内容符合规则要求"
    //   } else {
    //     tipEl.textContent =  "输入的内容不符合规则要求, 请重新输入"
    //   }
    // }

  </script>

</body>
</html>

修饰符flag的使用

g -> global

i -> ignore

m -> multiple

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    const message = "fdaa4 22242asfasdf2242"

    const re = /\d+/ig

    // \d -> 所有的数字 0~9
    console.log(message.match(re))

  </script>

</body>
</html>

4 正则表达式常见规则

规则 – 字符类(Character classes)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    const message = "fdaa4 22242asfasdf2242"

    const re = /\d+/ig

    // \d -> 所有的数字 0~9
    console.log(message.match(re))

    const re1 = /\d+/ig
  </script>

</body>
</html>

规则 – 锚点(Anchors)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    const message = "My name is WHY."

    // 字符串方法
    if (message.startsWith("my")) {
      console.log("以my开头")
    }
    if (message.endsWith("why")) {
      console.log("以why结尾")
    }

    // 正则: 锚点
    if (/^my/i.test(message)) {
      console.log("以my开头")
    }

    if (/why\.$/i.test(message)) {
      console.log("以why结尾")
    }


    const re = /^coder$/
    const info = "codaaaer"
    console.log(re.test(info)) // false

  </script>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // \w
    const message = "My name! is WHY."

    // 需求: name, name必须是一个单独的词
    // 词边界
    if (/\bname\b/i.test(message)) {
      console.log("有name, name有边界")
    }

    // 词边界的应用
    const infos = "now time is 11:56, 12:00 eat food, number is 123:456"
    const timeRe = /\b\d\d:\d\d\b/ig
    console.log(infos.match(timeRe))

  </script>

</body>
</html>

规则 – 转义字符串

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 定义正则: 对.转义
    const re = /\./ig
    const message = "abc.why"

    const results = message.match(re)
    console.log(results)


    // 特殊: /
    // const re2 = /\//

    // 获取到很多的文件名
    // jsx -> js文件
    const fileNames = ["abc.html", "Home.jsx", "index.html", "index.js", "util.js", "format.js"]
    // 获取所有的js的文件名(webpack)
    // x?: x是0个或者1个
    const jsfileRe = /\.jsx?$/
    // 1.for循环做法
    // const newFileNames = []
    // for (const filename of fileNames) {
    //   if (jsfileRe.test(filename)) {
    //     newFileNames.push(filename)
    //   }
    // }
    // console.log(newFileNames)

    // 2.filter高阶函数
    // const newFileNames = fileNames.filter(filename => jsfileRe.test(filename))
    // console.log(newFileNames)

  </script>

</body>
</html>

集合(Sets)和范围(Ranges)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // 手机号的规则: 1[3456789]033334444
    const phoneStarts = ["132", "130", "110", "120", "133", "155"]
    const phoneStartRe = /^1[3456789]\d/
    const filterPhone = phoneStarts.filter(phone => phoneStartRe.test(phone))
    console.log(filterPhone)

    const phoneNum = "133888855555"
    const phoneRe = /^1[3-9]\d{9}$/
    console.log(phoneRe.test(phoneNum))

    // 了解: 排除范围
    // \d -> [0-9]
    // \D -> [^0-9]

  </script>

</body>
</html>

量词(Quantifiers)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 1.量词的使用
    const re = /a{3,5}/ig
    const message = "fdaaa2fdaaaaaasf42532fdaagjkljlaaaaf"

    const results = message.match(re)
    console.log(results)

    // 2.常见的符号: +/?/*
    // +: {1,}
    // ?: {0,1}
    // *: {0,}

    // 3.案例: 字符串的html元素, 匹配出来里面所有的标签
    const htmlElement = "<div><span>哈哈哈</span><h2>我是标题</h2></div>"
    const tagRe = /<\/?[a-z][a-z0-9]*>/ig
    const results2 = htmlElement.match(tagRe)
    console.log(results2)

  </script>

</body>
</html>

贪婪( Greedy)和惰性( lazy)模式

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 1.贪婪模式/惰性模式
    const message = "我最喜欢的两本书: 《黄金时代》和《沉默的大多数》、《一只特立独行的猪》"

    // 默认.+采用贪婪模式
    // const nameRe = /《.+》/ig
    
    // const result1 = message.match(nameRe)
    // console.log(result1)

    // 使用惰性模式
    const nameRe = /《.+?》/ig
    
    const result1 = message.match(nameRe)
    console.log(result1)

  </script>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 1.捕获组
    const message = "我最喜欢的两本书: 《黄金时代》和《沉默的大多数》、《一只特立独行的猪》"

    // 使用惰性模式
    const nameRe = /(?:《)(?<why>.+?)(?:》)/ig
    const iterator = message.matchAll(nameRe)
    for (const item of iterator) {
      console.log(item)
    }

    // 2.将捕获组作为整体
    const info = "dfabcabcfabcdfdabcabcabcljll;jk;j"
    const abcRe = /(abc){2,}/ig
    console.log(info.match(abcRe))

  </script>

</body>
</html>

组(capturing group)

捕获组的补充

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // 1.将捕获组作为整体
    const info = "dfabcabcfabcdfdabcabcabcljcbacballnbanba;jk;j"
    const abcRe = /(abc|cba|nba){2,}/ig
    console.log(info.match(abcRe))

  </script>

</body>
</html>

5 正则练习-歌词解析

案例练习 – 歌词解析

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script src="./js/parse_lyric.js"></script>
  <script>
    /*
      currentTime: 2000

      [00:00.000] 作词 : 许嵩 -> { time: 0, content: "作词 : 许嵩" }
      [00:01.000] 作曲 : 许嵩 -> { time: 1000, content: "作曲 : 许嵩" }
      [00:02.000] 编曲 : 许嵩
      [00:22.240]天空好想下雨
    */
    const lyricString = "[00:00.000] 作词 : 许嵩\n[00:01.000] 作曲 : 许嵩\n[00:02.000] 编曲 : 许嵩\n[00:22.240]天空好想下雨\n[00:24.380]我好想住你隔壁\n[00:26.810]傻站在你家楼下\n[00:29.500]抬起头数乌云\n[00:31.160]如果场景里出现一架钢琴\n[00:33.640]我会唱歌给你听\n[00:35.900]哪怕好多盆水往下淋\n[00:41.060]夏天快要过去\n[00:43.340]请你少买冰淇淋\n[00:45.680]天凉就别穿短裙\n[00:47.830]别再那么淘气\n[00:50.060]如果有时不那么开心\n[00:52.470]我愿意将格洛米借给你\n[00:55.020]你其实明白我心意\n[00:58.290]为你唱这首歌没有什么风格\n[01:02.976]它仅仅代表着我想给你快乐\n[01:07.840]为你解冻冰河为你做一只扑火的飞蛾\n[01:12.998]没有什么事情是不值得\n[01:17.489]为你唱这首歌没有什么风格\n[01:21.998]它仅仅代表着我希望你快乐\n[01:26.688]为你辗转反侧为你放弃世界有何不可\n[01:32.328]夏末秋凉里带一点温热有换季的颜色\n[01:41.040]\n[01:57.908]天空好想下雨\n[01:59.378]我好想住你隔壁\n[02:02.296]傻站在你家楼下\n[02:03.846]抬起头数乌云\n[02:06.183]如果场景里出现一架钢琴\n[02:08.875]我会唱歌给你听\n[02:10.974]哪怕好多盆水往下淋\n[02:15.325]夏天快要过去\n[02:18.345]请你少买冰淇淋\n[02:21.484]天凉就别穿短裙\n[02:22.914]别再那么淘气\n[02:25.185]如果有时不那么开心\n[02:27.625]我愿意将格洛米借给你\n[02:30.015]你其实明白我心意\n[02:33.327]为你唱这首歌没有什么风格\n[02:37.976]它仅仅代表着我想给你快乐\n[02:42.835]为你解冻冰河为你做一只扑火的飞蛾\n[02:48.406]没有什么事情是不值得\n[02:52.416]为你唱这首歌没有什么风格\n[02:57.077]它仅仅代表着我希望你快乐\n[03:01.993]为你辗转反侧为你放弃世界有何不可\n[03:07.494]夏末秋凉里带一点温热\n[03:11.536]\n[03:20.924]为你解冻冰河为你做一只扑火的飞蛾\n[03:26.615]没有什么事情是不值得\n[03:30.525]为你唱这首歌没有什么风格\n[03:35.196]它仅仅代表着我希望你快乐\n[03:39.946]为你辗转反侧为你放弃世界有何不可\n[03:45.644]夏末秋凉里带一点温热有换季的颜色\n"

    // 一. 没有封装
    // 1.根据\n切割字符串
    const lyricLineStrings = lyricString.split("\n")
    // console.log(lyricLineStrings)

    // 2.针对每一行歌词进行解析
    // [01:22.550]夏末秋凉里带一点温热有换季的颜色
    const timeRe = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/i
    const lyricInfos = []
    for (const lineString of lyricLineStrings) {
      // 1.获取时间
      const result = lineString.match(timeRe)
      if (!result) continue
      const minuteTime = result[1] * 60 * 1000
      const secondTime = result[2] * 1000
      const mSecondTime = result[3].length === 3? result[3]*1: result[3]*10
      const time = minuteTime + secondTime + mSecondTime
      
      // 2.获取内容
      const content = lineString.replace(timeRe, "").trim()

      // 3.将对象放到数组中
      lyricInfos.push({ time, content })
    }
    console.log(lyricInfos)
    
    // 二.封装工具: 解析歌词
    // const lyricInfos = parseLyric(lyricString)
    // console.log(lyricInfos)

  </script>

</body>
</html>

6 正则练习-日期格式化

案例练习 – 时间格式化

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <h2 class="time"></h2>

  <script>

    // timestamp: 1659252290626
    // yyyy/MM/dd hh:mm:ss
    // yyyy*MM*dd hh-mm-ss
    // dayjs/moment
    function formatTime(timestamp, fmtString) {
      // 1.将时间戳转成Date
      const date = new Date(timestamp)

      // // 2.获取到值
      // const year = date.getFullYear()
      // const month = date.getMonth() + 1
      // const day = date.getDate()
      // const hour = date.getHours()
      // const minute = date.getMinutes()
      // const second = date.getSeconds()

      // // 3.创建正则
      // const yearRe = /y+/
      // const monthRe = /M+/

      // 2.正则和值匹配起来
      const dateO = {
        "y+": date.getFullYear(),
        "M+": date.getMonth() + 1,
        "d+": date.getDate(),
        "h+": date.getHours(),
        "m+": date.getMinutes(),
        "s+": date.getSeconds()
      }

      // 3.for循环进行替换
      for (const key in dateO) {
        const keyRe = new RegExp(key)
        if (keyRe.test(fmtString)) {
          const value = (dateO[key] + "").padStart(2, "0")
          fmtString = fmtString.replace(keyRe, value)
        }
      }

      return fmtString
    }

    // 某一个商品上架时间, 活动的结束时间
    const timeEl = document.querySelector(".time")
    const productJSON = {
      name: "iPhone",
      newPrice: 4999,
      oldPrice: 5999,
      endTime: 1659252301637
    }
    timeEl.textContent = formatTime(productJSON.endTime, "hh:mm:ss yyyy*MM*dd")

  </script>

</body>
</html>