天天看點

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

作者:valentinogagliardi

譯者:前端小智

來源:github

阿裡雲伺服器很便宜火爆,今年比去年便宜,10.24~11.11購買是1年86元,3年229元,可以點選 閱讀原文 進行參與。

為了保證的可讀性,本文采用意譯而非直譯。

重新介紹 HTML 表單

網頁不僅僅是用來顯示資料的。有了 HTML 表單,咱們可以收集和操作使用者資料。在本章中,通過建構一個簡單的 HTML 表單來學習表單的相關的知識。

在這個過程中,會了解更多關于 DOM 事件的資訊,從在

第8章

我們知道了一個

元素是一個 HTML 元素,它可能包含其他的子元素,比如:

  • 用于捕獲資料
  • 用于捕獲文本
  • 用于送出表單

在本章中,咱們建構一個包含

的表彰。理想情況下,每個

input

都應該具有

type

的屬性,該屬性訓示輸入類型: 例如

text

email

number

date

等。除了

type

屬性之外,可能還希望向每個表單元素添加

id

屬性。

input

textarea

也可以有一個

name

屬性。如果你們想在不使用 JS 的情況下發送表單,name 屬性非常重要。稍後會詳細介紹。

另外,将每個表單元素與

關聯也是一種常見的方式。在下面的示例中,會看到每個

label

for

屬性綁定對應

input

元素的

id

,作用是點選

label

元素就能讓

input

聚焦。

如果沒有填寫所有需要的資訊,使用者将無法送出表單。這是一個避免空資料的簡單驗證,進而防止使用者跳過重要字段。有了這些知識,現在就可以建立 HTML 表單了。建立一個名為 form.html 的新檔案并建構 HTML:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

如上所述,表單中的

input

具有正确的屬性,從現在開始,可以通過填充一些資料來測試表單。編寫 HTML 表單時,要特别注意

type

屬性,因為它決定了使用者能夠輸入什麼樣的資料。

HTML5 還引入了表單驗證:例如,類型為

email

的輸入隻接受帶有

“at”

符 号

@

的電子郵件位址。不幸的是,這是對電子郵件位址應用的惟一檢查:沒有人會阻止使用者輸入類似

[email protected]

這樣的電子郵件。它有

@

,但仍然是無效的(用于電子郵件輸入的

pattern

屬性可以幫助解決這個問題。

上有很多可用的屬性,我發現

minlength

maxlength

是最有用的兩個。在實戰中,它們可以阻止懶惰的垃圾郵件發送者發送帶有

“aa”

“testtest”

的表單。

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

有了這個表單,咱們就可以更進一步了,接着,來看下表單是如何工作的。

表單是如何工作

HTML 表單是 HTMLFormElement 類型的一個元素。與幾乎所有的 HTML 元素一樣,它連接配接到

HTMLElement

,後者又連接配接到

EventTarget

。當我們通路 DOM 元素時,它們被表示為 JS 對象。在浏覽器中試試這個:

const aForm = 
           

輸出是

“object”

,而像

HTMLElement

EventTarget

這樣的實體是函數:

console.log(
           

是以,如果任何 HTML 元素都連接配接到

EventTarget

,這意味着

EventTarget

的“執行個體”,如下:

const aForm = 
           

form

EventTarget

的一種專門化類型。每個

EventTarget

都可以接收和響應 DOM 事件(如第8章所示)。

DOM 事件有很多類型,比如

click

blur

change

等等。現在,咱們感興趣的是 HTML 表單特有的

submit

事件。當使用者單擊

input

type

為 “submit” 的按鈕(元素必須出現在表單中)時,就會分派

submit

事件,如下所示:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

請注意,

Submit

 就在表單内部。一些開發人員使用

input

方式:

隻要表單存在上面 列出的任何一種按鈕,那麼在相應表單控件擁有焦點的情況下,按Enter鍵就可以送出表單。(textarea 是一個例外,在文本中回車會換行。)如果表單裡沒有送出按鈕,按Enter鍵不會送出表單。

咱們的目标是擷取表單上的所有使用者輸入,是以,需要監聽

submit

事件。

const formSelector = 
           

DOM 還提供

document.forms

,這是頁面内所有表單的集合。咱們現在隻需要:

const formSelector = 
           

現在的想法是:給定一個表單選擇器,我們可以注冊一個事件監聽器來響應表單的發送。為了注冊監聽器,我們可以使用構造函數,并讓它調用一個名為

init

的方法。在與 form.html 相同的檔案夾中建立一個名為 form.js 的新檔案,并從一個簡單的類開始:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

咱們的事件監聽器是

this.handleSubmit

,與每個事件監聽器一樣,它可以通路名為

event

的參數。從第8章中應該知道,事件是實際分派的事件,其中包含有關動作本身的許多有用資訊。咱們來實作

this.handleSubmit

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

然後,執行個體化類

From

:

const formSelector = 
           

此時,在浏覽器中打開 form.html。輸入内容并點選“送出”。會發生什麼呢? 輸出如下:

//localhost:63342/little-javascript/code/ch10/form.html?name=Valentino&description=Trip+to+Spoleto&tak=We%27re+going+to+visit+the+city%21
           

這是怎麼回事?大多數 DOM 事件都有所謂的“預設行為”。

submit

事件尤其嘗試将表單資料發送到虛構的伺服器。這就是在沒有 JS的 情況下發送表單的方式,因為它是基于 Django、Rails和friends 等 web 架構的應用程式的一部分。

每個輸入值都映射到相應的

name

屬性。在本例中不需要

name

,因為這裡咱們想用 JS 來控制表單,是以需要禁用預設行為。可以通過調用

preventDefault

來禁用:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

儲存檔案,然後再次重新整理 form.html。嘗試填寫表格,然後單擊送出。會看到

event

對象列印到控制台:

event

對象的許多屬性中,還有

event.target

,這表明咱們的 HTML 表單與所有輸入一起儲存在那裡,來看看是否确實如此。

從 from 提取資料

為了擷取表單的值,通過檢查

event.target

,您将發現有一個名為

elements

的屬性。該屬性是表單中所有元素的集合。這個

elements

集合是一個有序清單,其中包含着表單的所有字段,例如

。如果嘗試使用

console.log(event.target.elements)

進行列印,則會看到:

0: input#name
           

每個表單字段在

elements

集合中的順序,與它們出現在标記中的順序相同,可以按照位置和

name

特性來通路它們。現在,咱們有兩種方法擷取輸入的值:

  • 通過類似數組的表示法:

    event.target.elements[0].value

  • 通過 id:

    event.target.elements.some_id.value

實際上,如果現在希望在每個表單元素上添加适當的

id

屬性,則可以通路與

event.target.elements.some_id

相同的元素,其中

id

是你配置設定給該屬性的字元串。由于

event.target.elements

首先是一個對象,是以還可以使用 ES6 對象解構:

const { name, description, task } = 
           

這種做法不是

100%

推薦的,例如在 TypeScript 你會得到一個錯誤,但隻要寫

“vanilla JS”

就可以了。現在有了這些值,咱們就可以完成

handleSubmit

了,在此過程中,還建立了另一個名為

saveData

的方法。現在它隻是将值列印到控制台:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

這種儲存資料的方式并不是最好的判斷。如果字段更改怎麼辦?現在咱們有了

name

task

description

,但将來可能會添加更多輸入,是以需要動态提取這些字段。當然,還要解決對象銷毀問題,來看看

event.target.elements

0: input#name
           

它看起來像一個數組。咱們使用

map

方法将其轉換為僅包含

name

description

task

(過濾按鈕類型 submit):

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

在浏覽器中嘗試一下并檢視控制台:

Uncaught 
           

“ .map不是函數”

。那麼

event.target.elements

到底是什麼?看起來像一個數組,但卻是另一種野獸:它是

HTMLFormControlsCollection

。在 第8章中,咱們對這些内容有所了解,并看到一些 DOM 方法傳回了

HTMLCollection

// Returns an HTMLCollection
           

HTML 集合看起來類似于數組,但是它們缺少諸如

map

filter

之類的用于疊代其元素的方法。仍然可以使用方括号表示法通路每個元素,我們可以通過 Array.from 将類似數組轉成真正的數組:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

通過

Array.from

方法将

event.target.elements

構造一個數組。

Array.from

接受一個映射函數作為第二個參數,進一步優化:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

重新整理 form.html,填寫表單,然後按“送出”。在控制台中看到以下數組:

"Valentino", "We're going to visit the city!", undefined]
           

最後,我想生成一個對象數組,其中每個對象還具有相關表單輸入的name屬性:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

再次重新整理 form.html,填寫表單,将看到:

good job,有一個

undefined

的空值,它來自

button

元素。

map

的預設行為是在“空”值的情況下傳回

undefined

。由于我們檢查了

if (formInput.type !== "submit")

,是以

button

元素未從

map

傳回,而是被

undefined

取代。我們可以稍後将其删除,現在來看看

localStorage

了解 localStorage 并完善類

咱們有時候需要為使用者保留一些資料,這樣做有很多原因。例如考慮一個筆記應用程式,使用者可以在 HTML表單中插入新内容,然後再回來檢視這些筆記。下次她打開頁面時,将在其中找到所有内容。

在浏覽器中儲存資料有哪些選項? 持久化資料的一種重要方法是使用資料庫,但這裡我們隻有一些 HTML、JS 和浏覽器。然而,在現代浏覽器中有一個内置的工具,它就像一個非常簡單的資料庫,非常适合我們的需要:

localStorage

localStorage

的行為類似于 JS 對象,它有一堆方法:

  • setItem

    用于儲存資料
  • getItem

    用于讀取資料
  • clear

    用于删除所有值
  • removeItem 用于清除對應的

    key

    的值

稍後我們将看到

setItem

getItem

,首先咱們先得有一個 form.html 檔案,内容如下:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

還有用于攔截送出事件的相關 JS 代碼:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

此時,咱們需要實作

this.saveData

來将每個筆記儲存到

localStorage

。這樣做時,需要保持盡可能的通用。換句話說,我不想用直接儲存到

localStorage

的邏輯來填充

this.saveData

相反,咱們為

Form

類提供一個外部依賴項(另一個類),該類的作用是實作實際代碼。将來我們将這些筆記資訊儲存到

localStorage

還是資料庫中都沒有關系。對于每種用例,我們應該能夠為

Form

提供不同的“存儲”,并随着需求的變化而從一種轉換為另一種。為此,我們首先調整構造函數以接受新的“存儲”參數:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

現在,随着類的複雜度增加,需要驗證構造函數的參數。作為一個用于處理 HTML 表單的類,咱們至少需要檢查

formSelector

是否是 form 類型的 HTML 元素:

constructor(formSelector, storage) {
    // Validating the arguments
    if (!(formSelector instanceof HTMLFormElement))
      throw Error(`Expected a form element got ${formSelector}`);
           

如果

formSelector

不是一個表單類型的,就會報錯。另外還要驗證

storage

,因為我們必須将使用者輸入存儲到某個地方。

存儲實作将是另一個類。在我們的例子中,可以是類似于通用

LocalStorage

的東西,在 form.js 中建立類

LocalStorage

現在,有了這個結構,我們就可以連接配接

Form

LocalStorage

  • Form

    中的

    saveData

    應該調用

    Storage

    實作
  • LocalStorage.save

    LocalStorage.get

    可以是靜态的

仍然在 form.js 中,如下更改類方法:

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

代碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。

原文:https://github.com/valentinogagliardi/Little-JavaScript-Book/blob/v1.0.0/manuscript/chapter10.md

交流

html表單form字型顔色_【JS 口袋書】第 11 章:HTML 表單及 localStorage 的使用

延伸閱讀

通過 41 個 問答方式快速了解學習 Git

重溫一下 JS 進階需要掌握的 13 個概念

13 個 JS 數組精簡技巧,一起來看看。

【JS 口袋書】第 10 章:使用異步 JavaScript

繼續閱讀