十二、正则表达式、元字符、替换修饰符、手势和对话框插件、字符串截取

news/2024/11/30 10:27:58/

1. 正则表达式

1.1 基本使用

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><!-- 正则表达式(Regular Expression)是一种字符串匹配的模式(规则)⚫ 使用场景:➢ 例如验证表单:手机号表单要求用户只能输入11位的数字 (匹配)➢ 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)--><script>// 1. 定义规则 其中/ /是正则表达式字面量;正则表达式也是对象const reg1 = /JS/const reg2 = new RegExp('JS')let str1 = 'JS学习'let str2 = 'TS学习'let str3 = '学习'// 2. 使用正则 test()方法 用来查看正则表达式与指定的字符串是否匹配,返回布尔型数据console.log(reg1.test(str1)) // trueconsole.log(reg1.test(str2)) // falseconsole.log(reg1.test(str3)) // falseconsole.log(reg2.test(str1)) // trueconsole.log(reg2.test(str2)) // falseconsole.log(reg2.test(str3)) // false</script>
</body></html>

1.2 元字符

1.2.1 边界符

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><!-- 普通字符:普通字符只能够匹配字符串中与它们相同的字符元字符(特殊字符):是一些具有特殊含义的字符,极大提高了灵活性和强大的匹配功能(边界符 量词 范围 字符类)--><!-- 边界符: 定义位置规则,必须用什么开头,用什么结尾^ 开始 ; $ 结束 ; ^和$在一起,表示必须是精确匹配--><script>const reg1 = /JS/const reg2 = /^JS/const reg3 = /JS$/const reg4 = /^JS$/let str1 = 'JS学习'let str2 = '学习JS'let str3 = 'JS'console.log(reg1.test(str1)) // trueconsole.log(reg2.test(str1)) // trueconsole.log(reg2.test(str2)) // falseconsole.log(reg3.test(str1)) // falseconsole.log(reg3.test(str2)) // trueconsole.log(reg4.test(str2)) // falseconsole.log(reg4.test(str3)) // true</script>
</body></html>

1.2.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>
</head><body><!-- 量词:用来设定某个模式重复次数 --><script>// 有开始结束,精确匹配// *:重复>=0 次const reg1 = /^钱*$/console.log(reg1.test('')) // tconsole.log(reg1.test('钱')) // tconsole.log(reg1.test('111')) // fconsole.log('-------------------')// +:重复>=1 次const reg2 = /^钱+$/console.log(reg2.test('')) // fconsole.log(reg2.test('钱')) // tconsole.log(reg2.test('钱钱')) // tconsole.log('-------------------')// ?:重复0次或1次const reg3 = /^钱?$/console.log(reg3.test('')) // tconsole.log(reg3.test('钱')) // tconsole.log(reg3.test('钱钱')) // fconsole.log('-------------------')// {n}:重复n次const reg4 = /^钱{3}$/console.log(reg4.test('钱钱')) // fconsole.log(reg4.test('钱钱钱')) // tconsole.log('-------------------')// {n,}:重复>=n 次const reg5 = /^钱{3,}$/console.log(reg5.test('钱钱')) // fconsole.log(reg5.test('钱钱钱')) // tconsole.log(reg5.test('钱钱钱钱')) // tconsole.log('-------------------')// {n,m}:重复n~m 次(包含n,m) 逗号左右两侧千万不要出现空格const reg6 = /^钱{3,5}$/console.log(reg6.test('钱钱')) // fconsole.log(reg6.test('钱钱钱')) // tconsole.log(reg6.test('钱钱钱钱钱')) // t</script>
</body></html>

1.2.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>
</head><body><!-- 范围:表示字符的范围,定义的规则限定在某个范围,比如只能是英文字母,或者数字等等,用 [] 表示范围[abc] 匹配包含的单个字符。也就是只有 a || b || c 这三个单字符返回true,可以理解为多选1[a-z] 连字符。来指定字符范围。[a-z] 表示 a 到 z 26个英文字母 [^abc] 取反符。[^a-z] 匹配除了小写字母以外的字符--><script>// 单个字符// 1. 多选1const reg1 = /[abc]/console.log(reg1.test('a')) // trueconsole.log(reg1.test('ac')) // trueconsole.log(reg1.test('cd')) // trueconsole.log(reg1.test('de')) // falseconsole.log('--------------')// 2. 连字符/* ➢ [a-z] 表示 a 到 z 26个英文字母都可以➢ [a-zA-Z] 表示大小写都可以➢ [0-9] 表示 0~9 的数字都可以*/const reg2 = /[a-f]/console.log(reg2.test('a')) // trueconsole.log(reg2.test('ac')) // trueconsole.log(reg2.test('ch')) // trueconsole.log(reg2.test('hj')) // falseconsole.log('--------------')// 3. 取反符const reg3 = /[^abc]/console.log(reg3.test('a')) // falseconsole.log(reg3.test('ac')) // falseconsole.log(reg3.test('cd')) // trueconsole.log(reg3.test('de')) // true</script>
</body></html>

案例1_验证用户名

<!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>验证用户名案例</title><style>dt,dd {margin: 0;position: relative;}dl {display: flex;width: 600px;height: 30px;line-height: 30px;}dl dt {margin-right: 5px;}dl input {width: 269px;height: 28px;padding-left: 5px;border: 1px solid #ccc;outline: none;background: transparent;line-height: 30px;border-radius: 5px;}.tip {display: none;position: relative;width: 220px;height: 30px;margin-left: 15px;border: 1px solid #f59fb1;color: #d93c3c;text-align: center;font-size: 14px;background-color: #fff2f5;border-radius: 5px;}.tip::before {content: '';position: absolute;top: 50%;left: -6px;width: 10px;height: 10px;background-color: #fff2f5;border-left: 1px solid #f59fb1;border-bottom: 1px solid #f59fb1;transform: translateY(-50%) rotate(45deg);}span {position: absolute;top: 9px;right: 10px;width: 15px;height: 15px;}.right {background: url(./images/right.png) no-repeat;}.wrong {background: url(./images/error1.png) no-repeat;}</style>
</head><body><dl><dt>用户名:</dt><dd><input type="text" class="uname"><span></span></dd><dd class="tip">输入6~16位数字字母-_组成</dd></dl><!-- 用户名验证案例需求:用户名要求用户英文字母,数字,下划线或者短横线组成,并且用户名长度为 6~16 位 /^[a-zA-Z0-9_-]{6-16}$/--><script>const ipt = document.querySelector('.uname')const rORw = document.querySelector('span')const tip = document.querySelector('.tip')/* 拓展补充:➢ blur 事件:当元素失去焦点时触发(不论表单元素的值是否发生改变)➢ change 事件:元素失去焦点并且表单元素的值发生改变才会触发*/const reg = /^[a-zA-Z0-9-_]{6,16}$/ipt.addEventListener('change', function () {if (reg.test(this.value)) {/* rORw.classList.add('right')rORw.classList.remove('wrong') */// span只能有一个类名,right或wrong,直接className替换即可rORw.className = 'right'tip.style.display = 'none'} else {/* rORw.classList.remove('right')rORw.classList.add('wrong') */rORw.className = 'wrong'tip.style.display = 'block'}})</script>
</body></html>

1.2.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>
</head><body><!-- 字符类:某些常见模式的简写方式,区分字母和数字\d 匹配0-9之间的任一数字,相当于[0-9]\D 匹配所有0-9以外的字符,相当于[^0-9]\w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]\W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]\s 匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f]\S 匹配非空格的字符,相当于[^\t\r\n\v\f] --><script>// 日期格式(简易 不规范)const reg = /^\d{4}-\d{1,2}-\d{1,2}$/console.log(reg.test('2024-11-26')) // trueconsole.log(reg.test('2025-1-1')) // true</script>
</body></html>

1.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>
</head><body><!-- 替换和修饰符replace 替换方法,可以完成字符的替换字符串.replace(/正则表达式/, '替换的文本')修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等/表达式/修饰符➢ i 是单词 ignore 的缩写,正则匹配时字母不区分大小写➢ g 是单词 global 的缩写,匹配所有满足正则表达式的结果--><script>const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'// 懒惰模式(默认),只匹配第一个,后面忽略const newStr1 = str.replace(/前端/, '鸿蒙')// replace 返回一个新的字符串,不修改原字符串console.log(str) // 欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神console.log(newStr1) // 欢迎大家学习鸿蒙,相信大家一定能学好前端,都成为前端大神// g 匹配所有满足正则表达式的结果const newStr2 = str.replace(/前端/g, '鸿蒙')console.log(newStr2) // 欢迎大家学习鸿蒙,相信大家一定能学好鸿蒙,都成为鸿蒙大神</script>
</body></html>

案例2_隐藏手机号中间四位

<!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>隐藏手机号中间四位案例.</title><style>.wrapper {width: 840px;height: 420px;background: url(./images/bg01.jpg) no-repeat center / cover;padding: 100px 250px;box-sizing: border-box;}.wrapper strong {font-size: 50px;}.wrapper span {color: #b10e0d;}</style>
</head><body><div class="wrapper"><strong>年会抽奖</strong><h1>获奖手机号:<span class="phone">???</span></h1></div><!-- 隐藏手机号中间四位案例 --><script>let tel = '13866668888'// 把手机号利用正则利用小括号划分为三部分const reg = /^(\d{3})(\d{4})(\d{4})$/// 在replace中,$1 对应第一个小括号内容,依次类推let str1 = tel.replace(reg, '$1****$3')// ${} -- 模板字符串${变量或表达式}// 字符串重复使用:字符串.repeat(次数) 实现let str2 = tel.replace(reg, `$1${'*'.repeat(4)}$3`)document.querySelector('.phone').innerHTML = str1</script>
</body></html>

2. JS插件

2.1 AlloyFinger 手势插件

<!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>AlloyFinger手势插件</title><style>.nav {width: 200px;height: 40px;border: 3px solid pink;}.item {width: 250px;height: 40px;line-height: 40px;background-color: skyblue;transition: all .3s;}.active {transform: translateX(-50px);}</style>
</head><body><div class="nav"><div class="item">AlloyFinger是腾讯AlloyTeam 开发</div></div><!-- AlloyFinger 是腾讯 AlloyTeam 团队开源的超轻量级 Web 手势插件,为元素注册各种手势事件 --><!-- 将AlloyFinger库引入当前文件 --><!-- 配置new AlloyFinger(element, { // element 是给哪个元素做滑动事件swipe: function (e) {// 滑动的时候要做的事情 e.direction 可以判断上下左右滑动 Left Right 等}})--><script src="./alloy_finger.js"></script><script>const item = document.querySelector('.item')new AlloyFinger(item, {swipe: function (e) {if (e.direction === 'Left') {item.classList.add('active')} else if (e.direction === 'Right') {item.classList.remove('active')}},// 手指触摸touchStart: function () {console.log('touchStart')},// 手指移动touchMove: function () {console.log('touchMove')},// 手指移开touchEnd: function () {console.log('touchEnd')}})</script>
</body></html>

2.2 M端事件

<!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>.box {width: 300px;height: 300px;background-color: pink;}</style>
</head><body><div class="box"></div><!-- M端(移动端)有自己独特的地方。比如触屏事件 touch(也称触摸事件)。touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。触屏touch事件touchstart 手指触摸到一个DOM元素时触发touchmove 手指在一个DOM元素上滑动时触发touchend 手指从一个DOM元素上移开时触发--><script>const box = document.querySelector('.box')box.addEventListener('touchstart', function () {console.log('touchstart')})box.addEventListener('touchmove', function () {console.log('touchmove')})box.addEventListener('touchend', function () {console.log('touchend')})</script>
</body></html>

2.3 a11y-dialog 对话框插件

<body><!-- 按钮 --><div class="btns"><button class="btn btn1">添加</button></div><!-- a11y --><!-- 1. 准备对话框容器 --><div class="dialog-container" id="dialog" aria-hidden="true"><!-- 2. 底部蒙层 --><div class="dialog-overlay" data-a11y-dialog-hide></div><!-- 3. 对话框结构 --><div class="dialog-content"><!-- 4. 关闭按钮 --><button type="button" class="dialog-close" data-a11y-dialog-hide>&times;</button><!-- 5. 标题 --><h1>测试对话框</h1><!-- 6. 内容 --><p>好看的对话框</p></div></div><!-- <script src="https://cdn.jsdelivr.net/npm/a11y-dialog@8/dist/a11y-dialog.min.js"></script> --><script src="./a11y-dialog.js"></script><script>const btn1 = document.querySelector('.btn1')// 获取对话框DOM容器const element = document.querySelector('#dialog')// 实例化对话框const dialog = new A11yDialog(element)btn1.addEventListener('click', function () {// 实例对话框调用 show 方法可以显示对话框dialog.show()})</script>
</body>

3. 字符串截取

  <script>const str = '我们都是前端大神啊'// 字符串截取// 1. substring// 最后一个字符console.log(str.substring(str.length - 1)) // 啊// 第一个字符console.log(str.substring(0, 1)) // 我// 2. str[] 字符串也有索引,console.log(str[0]) // 我</script>

4. 综合案例_移动端通讯录

<!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>通讯录案例</title><link rel="stylesheet" href="./iconfont/iconfont.css" /><link rel="stylesheet" href="./index.css" />
</head><body><div class="address-header">通讯录<i class="iconfont icon-tianjiayonghu"></i></div><div class="address-book"><!-- 添加item 核心区域--><!-- <div class="item"><p class="circle">华</p><p class="name">刘德华</p><p class="tel">15300588305</p><a class="del" href="javascript:;"><i class="iconfont icon-shanchutianchong" data-index="0"></i></a></div> --></div><button id="add" class="btn-add">添加联系人</button><!-- 模态框-添加联系人 --><div class="dialog-container" id="modal" aria-hidden="true" aria-labelledby="my-dialog-title"aria-describedby="my-dialog-description"><div class="dialog-overlay" data-a11y-dialog-hide></div><div class="dialog-content" role="document"><h1 id="my-dialog-title" class="title">添加联系人<button type="button" aria-label="Close this dialog window" class="el-dialog__headerbtn dialog-close"data-a11y-dialog-hide>取消</button></h1><!-- 联系人表单 --><div class="address-footer"><input id="name" type="text" placeholder="请输入姓名" /><input id="tel" type="text" placeholder="请输入手机号" /><button class="btn-ok" id="btnOK">确认</button></div></div></div><!-- 引入手势插件 --><script src="./js/alloy_finger.js"></script><!-- 引入弹窗插件 --><script src="./js/a11y-dialog.js"></script><script>// 本地存储let arr = JSON.parse(localStorage.getItem('contacts')) || []// 初始化数据/* let arr = [{ name: '周杰伦', tel: '13411112222' },{ name: '刘德华', tel: '13511112222' },{ name: '张学友', tel: '13711112222' },{ name: '岳云鹏', tel: '13911112222' },{ name: '迪丽热巴', tel: '13911112222' }] */const addressBook = document.querySelector('.address-book')// 渲染业务function render(data = arr) {let str = data.map((item, index) => {const { name, tel } = itemreturn `<div class="item"><p class="circle">${name.substring(name.length - 1)}</p><p class="name">${name}</p><p class="tel">${tel}</p><a class="del" href="javascript:;"><i class="iconfont icon-shanchutianchong" data-index="${index}"></i></a></div>`}).join('')addressBook.innerHTML = str/* 调用滑动功能每次 render 函数被调用后都会被执行,确保对新生成的 .item 元素进行了正确的事件绑定。 */swipe()}render()// 滑动业务// 滑动业务事件委托做不了,e.target值不确定 p div? --> forEach做// 要在渲染的时候准备好滑动功能等待用户滑动 -- 定义滑动函数,渲染函数中调用function swipe() {// forEach 遍历添加事件监听// 获取items元素若放到顶部,此时render函数未调用,HTML未填充item元素,获取元素失败 --> 滑动功能实现失败const items = document.querySelectorAll('.address-book .item')items.forEach(item => {new AlloyFinger(item, {swipe: function (e) {// console.log(e)if (e.direction === 'Left') {// 排他// 1. 页面打开默认有自带active类名,下行代码可行;默认无active找不到元素返回为空,控制台classList报错// document.querySelector('.address-book .active').classList.remove('active')// 2. css选择器书写错误 item和active同级类名,找不到item下的active符合条件的元素// document.querySelector('.item .active')?.classList.remove('active')const active = document.querySelector('.address-book .active')// 3.1 正确写法一 if判断/* if (active) {active.classList.remove('active')} */// 3.2 正确写法二 ?可选// active?.classList.remove('active')// 3.3 正确写法三 逻辑中断active && active.classList.remove('active')item.classList.add('active')} else if (e.direction === 'Right') {item.classList.remove('active')}}})})}// 删除业务 事件委托addressBook.addEventListener('click', function (e) {// console.log(e.target.dataset.index)if (e.target.classList.contains('icon-shanchutianchong')) {// confirm() 弹窗 返回值为布尔型let isDel = confirm('确定要删除嘛?')if (isDel) {arr.splice(e.target.dataset.index, 1)localStorage.setItem('contacts', JSON.stringify(arr))render()} else {document.querySelector('.active').classList.remove('active')}}})// 新增业务const btnAdd = document.querySelector('.btn-add')// 获取对话框DOM容器const modal = document.querySelector('#modal')// 实例化对话框const dialog = new A11yDialog(modal)btnAdd.addEventListener('click', function () {dialog.show()})const btnOK = document.querySelector('#btnOK')const uname = document.querySelector('#name')const tel = document.querySelector('#tel')btnOK.addEventListener('click', function () {// 验证数据合法?let unameReg = /^(?:[\u4e00-\u9fa5·]{2,16})$/let telReg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/let addName = uname.valuelet addTel = tel.valueif (!addName.trim() || !addTel.trim()) {alert('不能为空')return}if (!unameReg.test(addName)) {alert('姓名输入错误')return}if (!telReg.test(addTel)) {alert('电话输入错误')return}arr.unshift({ name: addName, tel: addTel })localStorage.setItem('contacts', JSON.stringify(arr))render()// 关闭添加联系人页面dialog.hide()uname.value = ''tel.value = ''})</script>
</body></html>

5. 作业

5.1 软考个人信息提交

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="index.css"></head><body><header><h1><img src="https://bm.ruankao.org.cn/asset/image/public/logo.png" alt=""><span>全国计算机技术与软件专业技术资格(水平)考试</span><span class="address">当前考区:北京</span></h1><div><span class="hello">xxx,您好!</span></div></header><main><section><h3>基本信息</h3><form action="#"><div class="form-item is-required"><label for="username">姓名:</label><div class="form-item-content"><input class="hm-input" type="text" id="username"><!-- <div class="form-error hide">用户名校验不通过,请输入1-4位的汉字</div> --><div class="form-error">用户名校验不通过,请输入1-4位的汉字</div></div></div><div class="form-item is-required"><label for="idcard">身份证:</label><div class="form-item-content"><input class="hm-input" type="text" id="idcard"><!-- <div class="form-error hide">请输入合法的身份证格式</div> --><div class="form-error">请输入合法的身份证格式</div></div></div><div class="form-item is-required"><label for="age">年龄:</label><div class="form-item-content"><input class="hm-input" type="text" id="age"><!-- <div class="form-error hide">请输入数字</div> --><div class="form-error">请输入数字</div></div></div><div class="form-item is-required"><label for="mobile">手机号:</label><div class="form-item-content"><input class="hm-input" type="text" id="mobile"><!-- <div class="form-error hide">请输入合法的手机号</div> --><div class="form-error">请输入合法的手机号</div></div></div><button class="submit">提交</button></form></section></main><!-- 需求如下:点击提交时,对表单进行数据格式校验:校验不通过,显示错误提示校验通过,跳转到成功页面--><script>const form = document.querySelector('form')const username = document.querySelector('#username')const idcard = document.querySelector('#idcard')const age = document.querySelector('#age')const mobile = document.querySelector('#mobile')// 正则const regUsername = /^(?:[\u4e00-\u9fa5]{1,4})$/const regIdcard = /^\d{6}((((((19|20)\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(((19|20)\d{2})(0[13578]|1[02])31)|((19|20)\d{2})02(0[1-9]|1\d|2[0-8])|((((19|20)([13579][26]|[2468][048]|0[48]))|(2000))0229))\d{3})|((((\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|((\d{2})(0[13578]|1[02])31)|((\d{2})02(0[1-9]|1\d|2[0-8]))|(([13579][26]|[2468][048]|0[048])0229))\d{2}))(\d|X|x)$/const regAge = /^\d{1,2}$/const regMobile = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/function REG(reg, el) {return reg.test(el.trim())}/* console.log(REG(regUsername, '小红')) // tconsole.log(REG(regUsername, '红')) // tconsole.log(REG(regUsername, '12352')) // f */form.addEventListener('submit', function (e) {if (REG(regUsername, username.value)) {// nextElementSibling 获取节点的下一个兄弟节点username.nextElementSibling.classList.add('hide')}if (REG(regIdcard, idcard.value)) {idcard.nextElementSibling.classList.add('hide')}if (REG(regAge, age.value)) {age.nextElementSibling.classList.add('hide')}if (REG(regMobile, mobile.value)) {mobile.nextElementSibling.classList.add('hide')}// console.log(document.querySelectorAll('.hide'))// console.log(document.querySelectorAll('.hide').length) // '4'// console.log(document.querySelectorAll('.hide').length == '4')// 阻止表单默认行为e.preventDefault()if (document.querySelectorAll('.hide').length == '4') {// console.log('success')location.href = './success.html'}})</script>
</body></html>

5.2 仿outlook邮箱

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./index.css"><link rel="stylesheet" href="./fonts/iconfont.css">
</head><body><header><span class="iconfont icon-hanbaobao"></span><span>收件箱</span><img src="./imgs/default-avatar.png" alt=""></header><ul class="mail-list"><!-- <li class="unread"><div class="group"><div class="status">标记已读</div><article><img src="./imgs/default-avatar.png" alt=""><div class="mail-info"><div><span class="from">Jack</span><time>2023/10/1</time></div><p>您好, 您之所以会收到此邮件,是因为我们正在更新 Microsoft 服务协议,该协议适用于您所使用的一个或多个 Microsoft产品或服务。我们之所以进行这些更新,是为了阐明我们的条款并确保这些条款仍对您保持透明。</p></div></article></div></li> --></ul><!-- <script src="https://unpkg.com/alloyfinger@0.1.16/alloy_finger.js"></script> --><script src="../alloy_finger.js"></script><script src="data.js"></script><script>const list = document.querySelector(".mail-list")function render(data = mails) {let str = data.map((el, index) => {const {from: { username, avatar },time,content,readStatus,} = elreturn `<li class="unread"><div class="group"><div class="status">标记已读</div><article><img src="${avatar}" alt=""><div class="mail-info"><div><span class="from">${username}</span><time>${time}</time></div><p>${content}/p></div></article></div></li>`}).join("")list.innerHTML = strswipefn()}render()// 滑动发生时 内容内标签变化 需再次渲染可实现滑动 封装滑动功能函数 渲染函数内调用function swipefn() {// 新增需求:向右滑动,出现操作区块,点击可修改邮件的阅读状态const lis = document.querySelectorAll(".mail-list li")// previousElementSibling 上一个兄弟节点lis.forEach((item) => {console.log(item.tagName) // LI// 查找子节点的子节点const status = item.children[0].children[0]// console.log(status)new AlloyFinger(item, {// swipe: function (e) {// console.log(e.target)if (e.direction === "Right") {item.classList.toggle('active')item.classList.contains('read')? status.innerHTML = '标记未读': status.innerHTML = '标记已读'}},touchStart: function (e) {if (e.target.classList.contains('status')) {item.classList.toggle('active')item.classList.toggle('read')status.innerHTML = '标记未读'}}})})}</script>
</body></html>


http://www.ppmy.cn/news/1551169.html

相关文章

python爬虫安装教程

Python爬虫是用于从网站上自动抓取信息的程序。在开始之前&#xff0c;请确保您了解并遵守目标网站的服务条款&#xff0c;尊重版权法&#xff0c;并且在合理合法的范围内使用爬虫技术。 安装环境 安装Python&#xff1a;首先确保您的计算机上已经安装了Python。推荐版本为3.…

Ubuntu FTP服务器的权限设置

在Ubuntu中设置FTP服务器的权限&#xff0c;主要涉及到用户权限管理和文件系统权限设置。以下是详细的步骤和配置方法&#xff1a; 安装FTP服务器软件 首先&#xff0c;确保已经安装了FTP服务器软件。常用的FTP服务器软件包括vsftpd和Pure-FTPd。以下是使用vsftpd作为示例的安…

PDF版地形图矢量出现的问题

项目描述&#xff1a;已建风电场道路测绘项目&#xff0c;收集到的数据为PDF版本的地形图&#xff0c;图上标注了项目竣工时期的现状&#xff0c;之后项目对施工区域进行了复垦恢复地貌&#xff0c;现阶段需要准确的知道实际复垦修复之后的道路及其它临时用地的面积 解决方法&…

【微服务】消息队列与微服务之微服务详解

微服务 单体架构 传统架构&#xff08;单机系统&#xff09;&#xff0c;一个项目一个工程&#xff1a;比如商品、订单、支付、库存、登录、注册等等&#xff0c;统一部署&#xff0c;一个进程all in one的架构方式&#xff0c;把所有的功能单元放在一个应用里。然后把整个应…

【人工智能】Python与强化学习:从零实现多臂老虎机(Multi-Armed Bandit)问题

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 强化学习是一种模仿生物行为的学习方法,在不确定环境中寻找最优策略。多臂老虎机(Multi-Armed Bandit, MAB)是强化学习的经典问题之一,模拟了在多个选择中如何平衡探索和利用,以获取最大的长期回报。…

【连接池】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

Android习题第二章布局

Android常见界面布局 本章习题 一、填空题 Android的常见布局都直接或者间接的继承自_______类。Android中的TableLayout继承自________。表格布局TableLayout可以通过________控制表格的行数。________布局通过相对定位的方式指定子控件的位置。在R.java文件中&#xff0c;…

Fanuc法那科机器人维修之参考位置详解

参考位置是预先设定好的一个或多个特定点位&#xff0c;当启用这一功能时&#xff0c;系统会实时且精确地判断机器人的当前关节角度是否处于预设参考位置的一定范围之内&#xff08;这个范围区间是可以根据实际需求进行设置的&#xff09;&#xff0c;并据此输出指定的信号。 这…