使用自訂 JavaScript 建立 UI 小工具
重要提示:此文件不適用於您目前選擇的格式 email!
在本教學中,您將學習如何使用 <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>
的協助。
若要進行此練習,您需要在電腦上執行網頁伺服器。如果您已經這樣做了,那就一切就緒!如果是這樣,根據您的設定,您可以透過在瀏覽器中輸入類似 https://127.0.0.1/amp-script-tutorial/starter_code/index.html
的 URL 來存取入門網頁。
或者,您可以使用類似 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。
如果您在任何時候需要偵錯腳本,您可以在 Web Worker 中設定 JavaScript 中的斷點,就像您使用任何 JavaScript 一樣。您只需要知道在哪裡找到它。
在 Chrome DevTools 中,開啟「Sources」標籤。在底部,您將看到一個長十六進位字串,如下所示。展開它,然後展開「no domain」區域,您將看到您的腳本
加入我們的 JavaScript
現在我們知道我們的 <amp-script>
正在運作,讓我們編寫一些 JavaScript!
我們要做的第一件事是抓取我們將要使用的 DOM 元素,並將它們儲存在全域變數中。我們的程式碼將使用密碼輸入、提交按鈕以及顯示密碼規則的區域。將這三個宣告新增到 validate.js
const passwordBox = document.getElementById("passwordBox");
const submitButton = document.getElementById("submitButton");
const rulesArea = document.getElementById("rules");
請注意,我們可以使用常規 DOM API 方法,例如 getElementById()
。儘管我們的程式碼在 worker 中執行,並且 worker 缺乏對 DOM 的直接存取,但 <amp-script>
提供了 DOM 的虛擬副本並模擬了一些常見的 API,此處 列出了這些 API。這些 API 為我們提供了足夠的工具來涵蓋大多數使用案例。但重要的是要注意,僅支援 DOM API 的一個子集。否則,<amp-script>
包含的 JavaScript 將非常龐大,抵消了 AMP 的效能優勢!
我們需要將這些 id 新增到兩個元素中。開啟 index.html
,找到密碼 <input>
和提交 <button>
,然後新增 id。同時在提交 <button>
中新增 disabled
屬性,以防止使用者在我們希望他們點擊之前點擊它。
<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>
的內容與我們的規則進行比較的邏輯。將一個名為 checkPassword()
的新函式新增到 initCheckPassword()
,就在右大括號之前
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 中使用 <amp-script>
編寫自己的 JavaScript。您已成功使用自己的自訂邏輯和 UI 功能增強了 <amp-form>
元件!隨意為您的新頁面新增更多功能!並且,要了解有關 <amp-script>
的更多資訊,請查看 參考文件。