|
|
|
|
|
在本文中,將介紹如何使用 JavaScript 構(gòu)建密碼生成器。
實(shí)例介紹
本密碼生成器將實(shí)現(xiàn)以下功能:
代碼分析
由于本文主要關(guān)注 JavaScript,我將跳過 CSS,但你可以在源碼下載包中找到相關(guān)樣式。
讓我們先看看我們需要什么標(biāo)記,然后我們將深入研究在 JavaScript 中實(shí)現(xiàn)功能(不要忘記包括的資源):
<!DOCTYPE html>
<html>
<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" />
<link rel="stylesheet" href="./app.css" />
</head>
<body>
<div id="app">
<div class="generate-pass">
<input type="text" />
<span class="copy">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 460 460" style="enable-background:new 0 0 460 460;" xml:space="preserve" data-js-selector="copy">
<path d="M425.934,0H171.662c-18.122,0-32.864,14.743-32.864,32.864v77.134h30V32.864c0-1.579,1.285-2.864,2.864-2.864h254.272 c1.579,0,2.864,1.285,2.864,2.864v254.272c0,1.58-1.285,2.865-2.864,2.865h-74.729v30h74.729 c18.121,0,32.864-14.743,32.864-32.865V32.864C458.797,14.743,444.055,0,425.934,0z" />
<path d="M288.339,139.998H34.068c-18.122,0-32.865,14.743-32.865,32.865v254.272C1.204,445.257,15.946,460,34.068,460h254.272 c18.122,0,32.865-14.743,32.865-32.864V172.863C321.206,154.741,306.461,139.998,288.339,139.998z M288.341,430H34.068 c-1.58,0-2.865-1.285-2.865-2.864V172.863c0-1.58,1.285-2.865,2.865-2.865h254.272c1.58,0,2.865,1.285,2.865,2.865v254.273h0.001 C291.206,428.715,289.92,430,288.341,430z" />
</svg>
</span>
</div>
<div class="inputs">
<label for="uppercase" data-js-selector="checkbox">
<input type="checkbox" id="uppercase" />
大寫字母
</label>
<label for="numbers" data-js-selector="checkbox">
<input type="checkbox" id="numbers" />
數(shù)字
</label>
<label for="symbols" data-js-selector="checkbox">
<input type="checkbox" id="symbols" />
字符
</label>
<div class="input-group">
密碼長(zhǎng)度
<div class="slider-container">
<input type="range" min="5" max="20" value="5" class="slider" data-js-selector="slider" />
<span class="value">5</span>
</div>
</div>
<button data-js-selector="button">生成密碼</button>
</div>
</div>
<script src="./app.js"></script>
</body>
</html>
請(qǐng)注意,我們正在使用data-js-selector
屬性,我們將在 JavaScript 中使用這些來獲取用戶事件的相關(guān) DOM 元素。最好不要為選擇器使用類,因?yàn)樗鼈兛赡軙?huì)發(fā)生變化并且它們是用于樣式的。這樣,很明顯它是專門針對(duì) JavaScript 的選擇器。
我想從 CSS 方面指出的一件重要事情是,確保添加pointer-events: none
到標(biāo)簽內(nèi)的復(fù)選框以始終在標(biāo)簽本身上注冊(cè)點(diǎn)擊事件,還要確保將script
標(biāo)記放在 body
標(biāo)記結(jié)束之前,以便在加載 JavaScript 時(shí),我們已經(jīng)可以訪問 DOM 元素。
事不宜遲,讓我們看看 JavaScript 部分。
設(shè)置可配置項(xiàng)
首先,我們要設(shè)置一些布爾標(biāo)志,稍后我們可以使用這些標(biāo)志來決定我們希望如何生成密碼。這包括諸如我們是否要使用某些字符或密碼長(zhǎng)度之類的事情。我們可以將其存儲(chǔ)在配置對(duì)象中(app.js):
const flags = {
uppercase: false,
numbers: false,
symbols: false,
length: 5
}
我們基本上為每個(gè)輸入都有一個(gè)標(biāo)志,可以更改最終生成密碼的輸出。我們也可以對(duì)選擇器做同樣的事情,這樣如果我們以后需要改變它們,我們只需要在一個(gè)地方做:
const selectors = {
copy: 'copy',
checkbox: 'checkbox',
slider: 'slider',
button: 'button',
sliderValue: document.querySelector('.value'),
input: document.querySelector('input[type="text"]')
}
請(qǐng)注意,我們只使用了querySelector
兩個(gè)元素,其余的都使用了簡(jiǎn)單的字符串。這是因?yàn)橐磺卸际亲址?,我們假設(shè)它引用了一個(gè)data-js-selector
用于用戶交互的屬性。
添加事件監(jiān)聽器
由于我們希望為多個(gè)事件偵聽器共享相同的邏輯,因此我們將只向應(yīng)用程序的根添加一個(gè)并將事件委托給必要的元素。為此,我們可以使用一個(gè)switch
聲明,使用data-js-selector
屬性:
document.querySelector('#app').addEventListener('click', event => {
switch (event.target.dataset.jsSelector) {
// Event listener for copy
case selectors.copy:
break;
// Event listeners for checkboxes
case selectors.checkbox:
break;
// Event listeners for slider
case selectors.slider:
break;
// Event listener for generate button
case selectors.button:
break;
}
})
我們將在每種情況下實(shí)施必要的事件偵聽器。它在屬性之間切換,并從我們上面定義的對(duì)象data-js-selector
中獲取正確的屬性。selectors
讓我們首先為復(fù)選框創(chuàng)建事件偵聽器,因?yàn)檫@只需要一行代碼:
case selectors.checkbox:
flags[event.target.control.id] = !event.target.control.checked
break;
我們?cè)谶@里所做的只是根據(jù)復(fù)選框是否被選中來更新其中一個(gè)標(biāo)志。我們可以通過引用control.id
(id復(fù)選框的屬性)來獲取復(fù)選框。請(qǐng)注意,它引用的是event.target
標(biāo)簽。每個(gè)標(biāo)簽都可以有一個(gè)控件,我們可以使用for
屬性連接它,這將使我們獲得id
。
使用 for
屬性連接到輸入的標(biāo)簽(應(yīng)與 id 匹配)
<label for="symbols" data-js-selector="checkbox">
<input type="checkbox" id="symbols" />
Symbols
</label>
因此,例如,一旦我們選中要使用的“符號(hào)”,這將轉(zhuǎn)換為以下內(nèi)容:
flags.symbols = true
如果我們現(xiàn)在選中復(fù)選框并將標(biāo)志對(duì)象的值記錄到控制臺(tái),我們可以看到每當(dāng)我們勾選一個(gè)復(fù)選框時(shí),它的值將相應(yīng)地更新。這將使我們稍后可以使用它們來決定如何生成密碼。
將標(biāo)志記錄到控制臺(tái)
為滑塊添加事件監(jiān)聽器
接下來,我們有滑塊。它與復(fù)選框略有不同,因?yàn)槲覀兪褂玫牟皇遣紶栔?,而是?shù)字。在這里,我們不僅要更新必要的標(biāo)志,還要更新顯示密碼當(dāng)前長(zhǎng)度的 UI。基于此,我們得到以下信息(移動(dòng)滑塊時(shí)更新狀態(tài)和 UI):
case selectors.slider:
const value = event.target.valueAsNumber
selectors.sliderValue.innerText = value
flags.length = value
break;
我們可以使用目標(biāo)事件上的屬性獲取滑塊的值作為數(shù)字,然后分配它來更新狀態(tài)和 UI。
復(fù)制密碼
我們只剩下兩件事要做。自己生成密碼,然后添加復(fù)制功能,這樣我們就可以通過單擊將代碼復(fù)制到剪貼板。讓我們從后者開始,因?yàn)樯纱a需要更多的解釋。在 JavaScript 中復(fù)制內(nèi)容到剪貼板可以通過以下方式實(shí)現(xiàn):
case selectors.copy:
selectors.input.select()
document.execCommand('copy')
break;
那么這里到底發(fā)生了什么?我們調(diào)用select
輸入來選擇輸入字段的內(nèi)容,然后運(yùn)行document.execCommand
“復(fù)制”以將所選值復(fù)制到剪貼板。這就是我們將文本復(fù)制到剪貼板所需的全部?jī)?nèi)容?,F(xiàn)在讓我們將注意力集中在生成密碼上。
生成密碼
對(duì)于這部分,我們可以創(chuàng)建一個(gè)新函數(shù)并在那里外包邏輯,這意味著我們實(shí)際上可以為事件監(jiān)聽器編寫一行代碼:
case selectors.button:
selectors.input.value = generatePassword()
break;
我們將輸入字段的值設(shè)置為函數(shù)的返回值generatePassword
。那么這個(gè)函數(shù)返回什么呢?它是生成的密碼的字符串表示形式。要生成密碼,我們首先需要知道哪些字符可供使用。為此,我們可以創(chuàng)建以下對(duì)象:
const generatePassword = () => {
const defaultCharacters = 'abcdefghijklmnopqrstuvwxyz'
const characters = {
uppercase: defaultCharacters.toUpperCase(),
numbers: '0123456789',
symbols: '~!@-#$'
}
}
默認(rèn)情況下,我們將從小寫的英文字母開始。我們toUpperCase
也可以調(diào)用此字符串來獲取字母的大寫版本。確保你還將其余可能的字符也定義為字符串,因?yàn)槲覀兊南敕ㄊ菑脑撟址须S機(jī)獲取一個(gè)值。我們還可以定義一個(gè)隨機(jī)符號(hào)列表以使其可用。
因此,基于這個(gè)字符列表,并基于當(dāng)前活動(dòng)的標(biāo)志,我們想要生成字符串的最終版本,以便我們?cè)谏刹糠謺r(shí)知道哪些字符可用。這意味著如果簽入數(shù)字,我們應(yīng)該得到以下字符串:
'abcdefghijklmnopqrstuvwxyz0123456789' -> 注意字符串末尾的數(shù)字
等等。那么我們?nèi)绾胃鶕?jù)標(biāo)志生成最終的字符串呢?我們可以使用一個(gè)數(shù)組,我們可以根據(jù)標(biāo)志選擇性地添加字符,然后將數(shù)組連接成一個(gè)字符串:
const characterList = [
defaultCharacters,
...flags.uppercase ? characters.uppercase : [],
...flags.numbers ? characters.numbers : [],
...flags.symbols ? characters.symbols : []
].join('')
默認(rèn)情況下,這包括默認(rèn)字符列表(英文字母表的小寫字母),并且可選地,如果它們的標(biāo)志設(shè)置為 true,我們可以添加其余字符。為此,我們可以使用帶有三元組合的擴(kuò)展運(yùn)算符來添加它或添加一個(gè)空數(shù)組。由于 spread 的工作方式,如果其中一個(gè)標(biāo)志是false,空數(shù)組也將被展開,這意味著不會(huì)添加任何內(nèi)容。然后我們可以使用join。
最后要做的是從函數(shù)實(shí)際返回密碼。為此,我們將用密碼的長(zhǎng)度填充一個(gè)數(shù)組,并從字符列表中隨機(jī)選擇一個(gè)字符。為此,我們可以使用以下公式:
return Array.from({ length: flags.length }, () => Math.floor(Math.random() * characterList.length))
.map(number => characterList[number])
.join('')
首先,我們需要?jiǎng)?chuàng)建一個(gè)數(shù)組。我們可以使用Array.from
. 它接受一個(gè)配置作為第一個(gè)參數(shù),我們可以在其中設(shè)置數(shù)組的長(zhǎng)度。我們希望長(zhǎng)度與密碼的長(zhǎng)度相匹配,所以我們可以在這里傳遞flags.length
。
第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),它定義了數(shù)組中每個(gè)元素的值。我們從characterList
中獲取一個(gè)隨機(jī)索引Math.random
。不要忘記我們需要對(duì)這個(gè)數(shù)字求底才能得到一個(gè)整數(shù)。最后,我們將得到一個(gè)包含隨機(jī)數(shù)列表的數(shù)組:
// 數(shù)組有密碼的長(zhǎng)度, 數(shù)字從字符列表長(zhǎng)度中獲得
[0, 23, 11, 52, 34] -> 這意味著密碼長(zhǎng)度為5個(gè)字符
現(xiàn)在我們有了一個(gè)隨機(jī)索引列表,我們可以使用映射從字符列表中選擇合適的字符,然后將所有內(nèi)容連接到一個(gè)字符串中。這意味著我們將獲得生成的密碼,以及以下內(nèi)容:
總結(jié)
本文介紹了原生 JavaScript 創(chuàng)建的一個(gè)密碼生成器!