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>