使用自訂 JavaScript 建立 UI 小工具
在本教學課程中,您將學習如何使用 <amp-script>
元件,此元件可讓開發人員在 AMP 中編寫自訂 JavaScript。您將使用它來建構一個小工具,以檢查密碼輸入欄位的內容,僅在符合特定需求時才允許提交。AMP 已經透過 <amp-form>
提供此功能,但 <amp-script>
將讓您能夠建立自訂體驗。
您需要的工具
- 現代網路瀏覽器
- HTML、CSS 和 JavaScript 的基本知識
- 以下任一項
- 本機網路伺服器和程式碼編輯器,例如 SublimeText 或 VSCode
- 或 CodePen、Glitch 或類似的線上遊樂場
背景資訊
AMP 旨在讓網站對使用者而言更快且更穩定。過多的 JavaScript 可能會使網頁速度變慢。但有時您需要建立 AMP 元件未提供的功能。在這種情況下,您可以使用 <amp-script>
元件來編寫自訂 JavaScript。
讓我們開始吧!
開始使用
若要取得入門程式碼,請下載或複製 此 github 儲存庫。完成後,cd
進入您建立的目錄。您會看到兩個目錄:starter_code
和 finished_code
。finished_code
包含您在本教學課程中將建立的內容。所以我們先不要看那個。而是 cd
進入 starter_code
。這包含一個網頁,該網頁僅使用 <amp-form>
實作我們的表單,而沒有 <amp-script>
的協助。
若要進行此練習,您需要在電腦上執行網路伺服器。如果您已經這樣做了,那就一切就緒了!如果是這樣,根據您的設定,您可以透過在瀏覽器中輸入 URL(例如 https://127.0.0.1/amp-script-tutorial/starter_code/index.html
)來存取入門網頁。
或者,您可以使用類似 serve 的工具來設定快速本機伺服器,這是一個基於 Node.js 的靜態內容伺服器。如果您尚未安裝 Node.js,請從 這裡 下載。安裝 Node 後,在命令列中輸入 npx serve
。然後您可以在這裡存取您的網站
https://127.0.0.1:5000/
您也可以自由使用線上遊樂場,例如 Glitch 或 CodePen。這個 包含與 github 儲存庫相同的程式碼,如果您願意,可以從這裡開始!
完成後,您將看到我們的入門網頁
在您最喜歡的程式碼編輯器中開啟 starter_code/index.html
。看看此表單的 HTML。請注意,密碼 <input>
包含此屬性
on="tap:rules.show; input-debounced:rules.show"
這告訴 AMP,當使用者點擊或按一下密碼 <input>
時,以及在他們在那裡輸入任何字元後,顯示規則 <div>
。我們更喜歡使用 focus
事件,這也將涵蓋使用者 Tab 鍵輸入的情況。至少在本教學課程撰寫時,AMP 沒有傳遞此事件,因此我們沒有此選項。別擔心。我們即將使用 <amp-script>
來修正這個問題!
密碼 <input>
包含另一個有趣的屬性
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-z\d]).{8,}$"
此正規表示式結合了一組較小的正規表示式,每個正規表示式都表達了我們的一個驗證規則。AMP 將不允許提交表單,直到輸入的內容符合為止。如果使用者嘗試,他們會看到一個錯誤訊息,但提供的詳細資訊很少
這種體驗是可以接受的 - 但遺憾的是,AMP 無法解釋我們的哪個驗證規則失敗。它無法知道,因為我們必須將規則壓縮成單一正規表示式。
現在,讓我們使用 <amp-script>
來建構更使用者友善的體驗!
使用 <amp-script> 重新建構
若要使用 <amp-script>
,我們需要匯入其自身的 JavaScript。開啟 index.html
並將以下內容新增至 <head>
。
<head>
...
<script async custom-element="amp-script" src="https://cdn.ampproject.org/v0/amp-script-0.1.js"></script>
...
</head>
<amp-script>
可讓我們內嵌或在外部檔案中編寫自己的 JavaScript。在本練習中,我們將編寫足夠的程式碼以值得使用單獨的檔案。建立一個名為 js
的新目錄,並在其中新增一個名為 validate.js
的新檔案。
<amp-script>
允許您的 JavaScript 操作其 DOM 子項 - 元件封閉的元素。它將這些 DOM 子項複製到虛擬 DOM 中,並讓您的程式碼存取此虛擬 DOM。在本練習中,我們希望我們的 JavaScript 控制我們的 <form>
及其內容。因此,我們將 <form>
包裝在 <amp-script>
元件中,如下所示
<amp-script src="js/validate.js" layout="fixed" sandbox="allow-forms" height="500" width="750">
<form method="post" action-xhr="#" target="_top" class="card">
...
</form>
</amp-script>
我們的 <amp-script>
包含屬性 sandbox="allow-forms"
。這告訴 AMP,指令碼修改表單內容是可以接受的。
由於 AMP 旨在保證快速、視覺上穩定的使用者體驗,因此它不會讓我們的 JavaScript 在任何時間對 DOM 進行不受限制的變更。如果 <amp-script>
元件的大小無法變更,您的 JavaScript 可以進行更多變更。在使用者互動後,它也允許更實質的變更。您可以在 參考文件 中找到詳細資訊。對於本教學課程,只需知道我們已指定一個不是 container
的 layout
類型,並且我們已使用 HTML 屬性來鎖定元件的大小。這表示任何 DOM 操作都僅限於頁面的特定區域。
如果您正在使用 AMP 驗證器 Chrome 擴充功能,您現在會看到錯誤訊息
#development=1
附加到您的 URL,AMP 會將驗證錯誤輸出到您的主控台。這是什麼意思?如果您的 <amp-script>
從外部檔案載入其 JavaScript,AMP 會要求您指定絕對 URL。我們可以透過使用 https://127.0.0.1/js/validate.js
來修正此問題。但 AMP 也要求使用 HTTPS。因此,我們仍然會收到驗證錯誤,並且在本機網路伺服器上設定 SSL 超出本教學課程的範圍。如果您想要這樣做,您可以依照 這篇文章 中的指示進行操作。
接下來,我們可以從表單中移除 pattern
屬性及其正規表示式:我們不再需要它了!
我們也將移除目前用於告訴 AMP 顯示我們密碼規則的 on
屬性。如上文預示,我們將改為使用 <amp-script>
來擷取瀏覽器的 focus
事件。
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-z\d]).{8,}$"
on="tap:rules.show; input-debounced:rules.show"
現在,讓我們確保我們的 <amp-script>
正在運作。開啟您建立的 validate.js
檔案並新增偵錯訊息
console.log("Hello, amp-script!");
前往您的瀏覽器,開啟主控台,然後重新載入頁面。確保您看到您的訊息!
我的 JavaScript 在哪裡?
<amp-script>
在 Web Worker 中執行您的 JavaScript。Web Worker 無法直接存取 DOM,因此 <amp-script>
讓 Worker 存取 DOM 的虛擬副本,並使其與真實 DOM 保持同步。<amp-script>
提供許多常見 DOM API 的模擬,您幾乎可以在 JavaScript 中以通常的方式使用所有這些 API。
如果您在任何時候需要偵錯您的指令碼,您可以像使用任何 JavaScript 一樣,在 Web Worker 中的 JavaScript 中設定中斷點。您只需要知道在哪裡找到它。
在 Chrome 開發人員工具中,開啟「來源」標籤。在底部,您會看到一個長十六進位字串,如下所示。展開該字串,然後展開「無網域」區域,您就會看到您的指令碼
加入我們的 JavaScript
現在我們知道我們的 <amp-script>
正在運作,讓我們編寫一些 JavaScript!
我們要做的第一件事是抓取我們將使用的 DOM 元素,並將這些元素儲存在全域變數中。我們的程式碼將使用密碼輸入、提交按鈕和顯示密碼規則的區域。將這三個宣告新增至 validate.js
const passwordBox = document.getElementById("passwordBox");
const submitButton = document.getElementById("submitButton");
const rulesArea = document.getElementById("rules");
請注意,我們能夠使用像 getElementById()
這樣的常規 DOM API 方法。雖然我們的程式碼在 Worker 中執行,並且 Worker 無法直接存取 DOM,但 <amp-script>
提供了 DOM 的虛擬副本並模擬了一些常見的 API,在此處 列出。這些 API 為我們提供了足夠的工具來涵蓋大多數使用案例。但務必注意,僅支援 DOM API 的子集。否則,包含在 <amp-script>
中的 JavaScript 將會非常龐大,從而否定 AMP 的效能優勢!
我們需要將這些 ID 新增至兩個元素。開啟 index.html
,找到密碼 <input>
和提交 <button>
,然後新增 ID。也將 disabled
屬性新增至提交 <button>
,以防止使用者在我們想要他們點擊之前點擊它。
<input type=password
id="passwordBox"
...
<button type="submit" id="submitButton" tabindex="3" disabled>Submit</button>
重新載入頁面。您可以透過檢查主控台來驗證這些全域變數是否已正確設定,就像您可以使用非 Worker JavaScript 一樣
我們還將 ID 新增至 <div id="rules">
中的每個 <li>
。其中每一個都包含一個個別規則,我們想要控制其顏色。我們將移除每個 class="invalid"
實例。我們的新 JavaScript 將在需要時新增它!
<ul>
<li id="lower">Lowercase letter</li>
<li id="upper">Capital letter</li>
<li id="digit">Digit</li>
<li id="special">Special character (@$!%*?&)</li>
<li id="eight">At least 8 characters long</li>
</ul>
在 JavaScript 中實作密碼檢查
接下來,我們將從 pattern
屬性中解壓縮正規表示式。每個正規表示式都代表我們的其中一個規則。讓我們在 validate.js
的底部新增一個物件對應,將每個規則與它檢查的準則建立關聯。
const checkRegexes = {
lower: /[a-z]/,
upper: /[A-Z]/,
digit: /\d/,
special: /[^a-zA-Z\d]/i,
eight: /.{8}/
};
設定這些全域變數後,我們就可以編寫檢查密碼並相應調整 UI 的邏輯。我們將把我們的邏輯放在一個名為 initCheckPassword
的函式中,該函式接受單一引數 - 密碼 <input>
的 DOM 元素。這種方法方便地將 DOM 元素儲存在閉包中。
function initCheckPassword(element) {
}
接下來,讓我們使用我們需要的函式和事件監聽器指派來填入 initCheckPassword
。首先,新增一個小函式,如果規則通過,則將個別規則 <li>
變為綠色 - 另一個函式在規則失敗時將其變為紅色。
function initCheckPassword(el) {
const checkPass = (el) => {
el.classList.remove("invalid");
el.classList.add("valid");
};
const checkFail = (el) => {
el.classList.remove("valid");
el.classList.add("invalid");
};
};
讓我們讓這些 valid
和 invalid
類別實際上將文字變為綠色或紅色。回到 index.html
,並將這兩個規則新增至 <style amp-custom>
標籤
li.valid {
color: #2d7b1f;
}
li.invalid {
color:#c11136;
}
現在我們準備好新增邏輯,以根據我們的規則檢查密碼 <input>
的內容。在 initCheckPassword()
中新增一個名為 checkPassword()
的新函式,緊接在右大括號之前
const checkPassword = () => {
const password = element.value;
let failed = false;
for (const check in checkRegexes) {
let li = document.getElementById(check);
if (password.match(checkRegexes[check])) {
checkPass(li);
} else {
checkFail(li);
failed = true;
}
}
if (!failed) {
submitButton.removeAttribute("disabled");
}
};
此函式執行以下操作
- 抓取密碼
<input>
的內容。 - 建立一個名為
failed
的旗標,初始化為false
。 - 迭代我們的每個正規表示式,並針對密碼測試每個正規表示式
- 如果密碼未通過測試,請呼叫
checkFail()
以將對應的規則變為紅色。此外,將failed
設定為true
。 - 如果密碼通過測試,請呼叫
checkPass()
以將對應的規則變為綠色。
- 如果密碼未通過測試,請呼叫
- 最後,如果沒有規則失敗,則密碼有效,並且我們啟用「提交」按鈕。
我們現在只需要幾個事件監聽器。還記得我們如何在 AMP 中無法使用 focus
事件嗎?在 <amp-script>
中,我們可以。每當密碼 <input>
收到 focus
事件時,我們都會顯示規則。每當使用者在該輸入中按下按鍵時,我們都會呼叫 checkPassword()
。
將這兩個事件監聽器新增至 initCheckPassword()
的底部,緊接在右大括號之前
element.addEventListener("focus", () => rulesArea.removeAttribute("hidden"));
element.addEventListener("keyup", checkPassword);
最後,在 validate.js
的最末尾,新增一行,使用密碼 <input>
DOM 元素初始化 initCheckPassword
initCheckPassword(passwordBox);
我們的邏輯現在已完成!當密碼符合我們所有的條件時,所有規則都將變為綠色,並且我們的提交按鈕將被啟用。您現在應該能夠進行如下互動
如果您遇到困難,您可以隨時參考 finished_code
目錄中的工作程式碼。
恭喜!
您已學習如何使用 <amp-script>
在 AMP 中編寫您自己的 JavaScript。您已成功使用您自己的自訂邏輯和 UI 功能來增強 <amp-form>
元件!隨時為您的新頁面新增更多功能!並且,若要深入瞭解 <amp-script>
,請查看 參考文件。