mini project
密码生成器
随机的大写字母,小写字母,数字,特殊字符
字母:使用fromCharCode
静态方法返回由指定的 UTF-16 码元序列创建的字符串。65表示大写字母A,97表示小写字母a
1 2
| String.fromCharCode(65 + Math.floor(Math.random() * 26)) String.fromCharCode(97 + Math.floor(Math.random() * 26))
|
特殊字符:把可用的特殊字符放在字符串中
随机字符生成函数和对应的选项生成映射关系:使用对象的键值对形式
1 2 3 4 5 6
| const randomFunc = { upper: getUp, lower: getLow, num: getNumber, sym: getSymbol }
|
对应的选项名和对应选项的布尔值(选项名变量)生成映射关系
1 2
| const typesArr = [{ upper }, { lower }, { num }, { sym }]
|
使用filter筛选出为真的选项名
1 2 3 4 5
| const needArr = typesArr.filter(item => { return Object.values(item)[0] })
|
再用选项名获取对应的随机字符函数来拼接密码
1 2 3 4 5
| needArr.forEach(item => { const key = Object.keys(item)[0] pwd += randomFunc[key]() })
|
js代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| const result = document.querySelector('.result') const btn = document.querySelector('.btn') const symbols = ['!', '@', '#', '$', '%', '^', '&', '*', '>', '<'] const icon = document.querySelector('.icon') btn.addEventListener('click', () => { const upper = document.getElementById('upper').checked const lower = document.getElementById('lower').checked const num = document.getElementById("num").checked const sym = document.getElementById("sym").checked const len = +document.getElementById('len').value console.log('111') result.innerText = generator(upper, lower, num, sym, len) })
icon.addEventListener('click', () => { const pass = result.innerText; if (!pass) { return; } navigator.clipboard.writeText(pass); alert('Password copied to clipboard!') }) const randomFunc = { upper: getUp, lower: getLow, num: getNumber, sym: getSymbol } function generator(upper, lower, num, sym, len) { let pwd = '' console.log('222') const typesArr = [{ upper }, { lower }, { num }, { sym }] console.log(typesArr) const needCount = upper + lower + num + sym if (needCount === 0) { return '' } const needArr = typesArr.filter(item => { return Object.values(item)[0] }) console.log(needArr) for (let i = 0; i < len; i += needCount) { console.log(len) needArr.forEach(item => { const key = Object.keys(item)[0] pwd += randomFunc[key]() }) } console.log(pwd) const finalPwd = pwd.slice(0, len)
console.log('333') return finalPwd } function getUp() { return String.fromCharCode(65 + Math.floor(Math.random() * 26)) } function getLow() { return String.fromCharCode(97 + Math.floor(Math.random() * 26)) } function getNumber() { return Math.floor(Math.random() * 10) } function getSymbol() { return symbols[Math.floor(Math.random() * 10)] }
|
- ASCII 编码:
- ASCII(American Standard Code for Information Interchange)是一种最初设计用于表示英语字符集的字符编码方案。
- ASCII 使用 7 位二进制数(0到127)来表示128个字符,包括基本的拉丁字母、数字、标点符号等。
- ASCII 编码是单字节编码,每个字符占用一个字节。
- UTF 编码:
- UTF(Unicode Transformation Format)是一种更为通用的字符编码方案,旨在表示全球范围内的所有语言的字符。
- UTF-8、UTF-16、UTF-32 是不同的 UTF 编码方案,使用不同的方式表示字符码点。
- UTF-8 是一种可变长度编码,UTF-16 是一种使用 2 或 4 字节表示的编码,UTF-32 是一种固定长度编码。
- UTF 编码兼容 ASCII,即 ASCII 字符的 UTF 编码值与其 ASCII 编码值相同。
关系:
- 所有的 ASCII 字符在 UTF 编码中有相同的编码值。UTF-8 编码中,ASCII 字符的编码与 ASCII 编码完全相同。
- UTF 编码扩展了 ASCII,使得它能够表示更广泛的字符集,包括拉丁字母以外的字符。
虽然 ASCII 编码和 UTF 编码有关联,但 UTF 编码是更为通用和灵活的编码方案,而 ASCII 可以看作是 UTF 的一个子集。 UTF 编码的出现主要是为了解决 ASCII 的局限性,使得计算机系统能够更好地处理和交换全球范围内的多语言字符。
编码方式常见的两个概念
码点值(字符码元值): 这是指字符在 Unicode 中的唯一标识符。每个字符都被赋予一个唯一的码点,这是一个整数值。例如,拉丁字母 “A” 在 Unicode 中的码点是 U+0041,U+是UTF编码方式的前缀,0041是16进制,十进制表示就是65。这个码点是字符的抽象标识。编码值(Encoded Value): 这是指字符码元值在特定字符编码方案下的实际存储形式。由于计算机内部处理数据的方式通常是使用字节,所以字符码元值需要以某种方式进行编码以便存储和传输。不同的字符编码方案使用不同的规则将字符码元值映射到字节序列。
有几种常见的 UTF 编码方案,其中最常见的是 UTF-8、UTF-16 和 UTF-32,用于表示 Unicode 字符。
按钮有关联
如果按钮之间有关联,比如有三个按钮选中的话,其中一个按钮就要取消选中。怎么确定三个按钮是否选中状态呢
利用input的id和label的for属性可以关联,label作按钮样式,用css写开启按钮的样式和关闭按钮的样式,开启和关闭通过input类型为checkbox的复选框的选中和未选中状态。
记事本
Element.closest()
方法用来获取:匹配特定选择器且离当前元素最近的祖先元素(也可以是当前元素本身)。如果匹配不到,则返回 null
。用这个方法来获取被点击元素的祖先元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const delEls = document.querySelectorAll('.fas.fa-trash') const notes = document.querySelectorAll('.note') const add = document.querySelector('.add') const noteContainer = document.querySelector('.notes') delEls.forEach(item => { item.addEventListener('click', (e) => { const grandparent = e.target.closest('.note') if (grandparent) { noteContainer.removeChild(grandparent) }
}) }) add.addEventListener('click', () => { const addnote = document.createElement('div') addnote.classList.add('note') addnote.innerHTML = ` <div class="select"> <div class="icon"> <i class="fas fa-pen"></i> <i class="fas fa-trash"></i> </div> </div> <textarea name="texts" id="text" cols="30" rows="10"></textarea> ` noteContainer.appendChild(addnote) })
|
为什么新添加的note无法点击删除图标被删除
在添加新的 note 元素时给该元素绑定了点击事件处理程序。然而,这些事件处理程序是在页面加载时绑定的,对于后来动态添加的元素并不会生效。两种解决方法:
1.事件委托(Event Delegation)通过将点击事件处理程序绑定到 noteContainer(或其父级),然后在事件处理程序中检查点击的元素是否是删除图标,从而实现对动态添加的元素的监听。
1 2 3 4 5 6 7 8
| noteContainer.addEventListener('click', (e) => { if (e.target.classList.contains('fas') && e.target.classList.contains('fa-trash')) { const grandparent = e.target.closest('.note'); if (grandparent) { noteContainer.removeChild(grandparent); } } });
|
- 为新添加的
note
元素单独绑定事件处理程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| add.addEventListener('click', () => { const addnote = document.createElement('div'); addnote.classList.add('note'); addnote.innerHTML = ` <div class="select"> <div class="icon"> <i class="fas fa-pen"></i> <i class="fas fa-trash"></i> </div> </div> <textarea name="texts" id="text" cols="30" rows="10"></textarea> `; addnote.querySelector('.fa-trash').addEventListener('click', () => { noteContainer.removeChild(addnote); });
noteContainer.appendChild(addnote); });
|
轮播图和图片导航
轮播图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <head> <style> .box{ height:500px; width:300px; <!-- 使用display可以让img在水平方向排列,而且会溢出显示(因为img是替换元素,不同于div,不会溢出显示),可以使用overflow:hidden;来遮住溢出显示,但是可以使用transition过渡效果来实现transform:translateX()。 --> display:flex; } img{ height:500px; width:300px; } </style> </head> <body> <div class="box"> <img/> <img/> <img/> </div> </body>
|
图片导航(点击导航栏ul li切换图片):使用子绝父相
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| <head> <style> .iphone { height: 500px; width: 300px; background-color: blue; overflow: hidden; position: relative; }
img { position: absolute; width: 300px; height: 400px; opacity:0; } img.show{ opacity:1; } nav{ position:absolute; bottom:0; margin-top:-5px; width:100% } ul{ list-style-type:none; display:flex; padding:0; margin:0; } ul li{ <!-- 让弹性盒模型中的子元素宽度相等--> flex:1; <!--水平居中--> text-align: center; } </style> </head> <body> <div class="iphone"> <img class="show"/> <img/> <nav> <ul> <li class="active"></li> <li></li> </ul> </nav> </div> <script> imgs.forEach((item,idx)=>{ item.addEventListener('click',()={ item.classList.add('show') lis[idx].classList.add('active') }) }) </script> </body>
|
背景图片模糊
当你直接给 body
的背景图片设置 opacity
时,整个 body
的内容,包括所有的子元素,都会受到这个 opacity
的影响。这是因为 opacity
属性会影响元素及其所有后代元素的可见性。使用 body::before
的方式是一种常见的解决方案,通过创建一个伪元素(:before
)来包裹整个页面内容,并为这个伪元素设置 opacity
。这样做的效果是只有伪元素及其子元素受到 opacity
的影响,而不会影响到 body
的其他内容。但是这样不方便使用js设置伪元素的opacity,如果要有交互就不要使用这种方法。
可以用一个单独的div来装一个100vh,100vw的背景图片,并设置这个div的position:absolute;不影响后续的元素添加在body。注意:这个div的top,left,bottom,right都要设置才能成功显示,一个都不能少。
css3有一个滤镜属性filter,比opacity有更多效果,比如模糊filter:blur(8px);
值越大越模糊,灰度filter:grayscale(100%);
全灰