国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript 編程精解 中文第三版 十八、HTTP 和表單

mengera88 / 961人閱讀

摘要:版本號后面是響應(yīng)狀態(tài),首先是一個三位的狀態(tài)碼,然后是一個可讀的字符串。以開頭的狀態(tài)碼表示請求成功。是最著名的狀態(tài)碼了,表示找不到資源。調(diào)用返回一個,它解析為一個對象,該對象包含服務(wù)器響應(yīng)的信息,例如狀態(tài)碼和協(xié)議頭。

來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目

原文:HTTP and Forms

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

自豪地采用谷歌翻譯

部分參考了《JavaScript 編程精解(第 2 版)》

通信在實(shí)質(zhì)上必須是無狀態(tài)的,從客戶端到服務(wù)器的每個請求都必須包含理解請求所需的所有信息,并且不能利用服務(wù)器上存儲的任何上下文。

Roy Fielding,《Architectural Styles and the Design of Network-based Software Architectures》

我們曾在第 13 章中提到過超文本傳輸協(xié)議(HTTP),萬維網(wǎng)中通過該協(xié)議進(jìn)行數(shù)據(jù)請求和傳輸。在本章中會對該協(xié)議進(jìn)行詳細(xì)介紹,并解釋瀏覽器中 JavaScript 訪問 HTTP 的方式。

協(xié)議

當(dāng)你在瀏覽器地址欄中輸入eloquentjavascript.net/18_http.html時,瀏覽器會首先找到和eloquentjavascript.net相關(guān)的服務(wù)器的地址,然后嘗試通過 80 端口建立 TCP 連接,其中 80 端口是 HTTP 的默認(rèn)通信端口。如果該服務(wù)器存在并且接受了該連接,瀏覽器可能發(fā)送如下內(nèi)容。

GET /18_http.html HTTP/1.1
Host: eloquentjavascript.net
User-Agent: Your browser"s name

然后服務(wù)器會通過同一個鏈接返回如下內(nèi)容。

HTTP/1.1 200 OK
Content-Length: 65585
Content-Type: text/html
Last-Modified: Mon, 08 Jan 2018 10:29:45 GMT


... the rest of the document

瀏覽器會選取空行之后的響應(yīng)部分,也就是正文(不要與 HTML 標(biāo)簽混淆),并將其顯示為 HTML 文檔。

由客戶端發(fā)出的信息叫作請求。請求的第一行如下。

GET /17_http.html HTTP/1.1

請求中的第一個單詞是請求方法。GET表示我們希望得到一個我們指定的資源。其他常用方式還有DELETE,用于刪除一個資源;PUT用于替換資源;POST用于發(fā)送消息。需要注意的是服務(wù)器并不需要處理所有收到的請求。如果你隨機(jī)訪問一個網(wǎng)站并請求刪除主頁,服務(wù)器很有可能會拒絕你的請求。

方法名后的請求部分是所請求的資源的路徑。在最簡單的情況下,一個資源只是服務(wù)器中的一個文件。不過,協(xié)議并沒有要求資源一定是實(shí)際文件。一個資源可以是任何可以像文件一樣傳輸?shù)臇|西。很多服務(wù)器會實(shí)時地生成這些資源。例如,如果你打開github.com/marijnh,服務(wù)器會在數(shù)據(jù)庫中尋找名為marijnjh的用戶,如果找到了則會為該用戶的生成介紹頁面。

請求的第一行中位于資源路徑后面的HTTP/1.1用來表明所使用的 HTTP 協(xié)議的版本。

在實(shí)踐中,許多網(wǎng)站使用 HTTP v2,它支持與版本 1.1 相同的概念,但是要復(fù)雜得多,因此速度更快。 瀏覽器在與給定服務(wù)器通信時,會自動切換到適當(dāng)?shù)膮f(xié)議版本,并且無論使用哪個版本,請求的結(jié)果都是相同的。 由于 1.1 版更直接,更易于使用,因此我們將專注于此。

服務(wù)器的響應(yīng)也是以版本號開始的。版本號后面是響應(yīng)狀態(tài),首先是一個三位的狀態(tài)碼,然后是一個可讀的字符串。

HTTP/1.1 200 OK

以 2 開頭的狀態(tài)碼表示請求成功。以 4 開頭的狀態(tài)碼表示請求中有錯誤。404 是最著名的 HTTP 狀態(tài)碼了,表示找不到資源。以 5 開頭的狀態(tài)碼表示服務(wù)器端出現(xiàn)了問題,而請求沒有問題。

請求或響應(yīng)的第一行后可能會有任意個協(xié)議頭,多個形如name: value的行表明了和請求或響應(yīng)相關(guān)的更多信息。這些是示例響應(yīng)中的頭信息。

Content-Length: 65585
Content-Type: text/html
Last-Modified: Thu, 04 Jan 2018 14:05:30 GMT

這些信息說明了響應(yīng)文檔的大小和類型。在這個例子中,響應(yīng)是一個 65585 字節(jié)的 HTML 文檔,同時也說明了該文檔最后的更改時間。

多數(shù)大多數(shù)協(xié)議頭,客戶端或服務(wù)器可以自由決定需要在請求或響應(yīng)中包含的協(xié)議頭,不過也有一些協(xié)議頭是必需的。例如,指明主機(jī)名的Host頭在請求中是必須的,因?yàn)橐粋€服務(wù)器可能在一個 IP 地址下有多個主機(jī)名服務(wù),如果沒有Host頭,服務(wù)器則無法判斷客戶端嘗試請求哪個主機(jī)。

請求和響應(yīng)可能都會在協(xié)議頭后包含一個空行,后面則是消息體,包含所發(fā)送的數(shù)據(jù)。GETDELETE請求不多帶帶發(fā)送任何數(shù)據(jù),但PUTPOST請求則會。同樣地,一些響應(yīng)類型(如錯誤響應(yīng))不需要有消息體。

瀏覽器和 HTTP

正如上例所示,當(dāng)我們在瀏覽器地址欄輸入一個 URL 后瀏覽器會發(fā)送一個請求。當(dāng) HTML 頁面中包含有其他的文件,例如圖片和 JavaScript 文件時,瀏覽器也會一并獲取這些資源。

一個較為復(fù)雜的網(wǎng)站通常都會有 10 到 200 個不等的資源。為了可以很快地取得這些資源,瀏覽器會同時發(fā)送多個GET請求,而不是一次等待一個請求。此類文檔都是通過GET方法來獲取的。

HTML頁面可能包含表單,用戶可以在表單中填入一些信息然后由瀏覽器將其發(fā)送到服務(wù)器。如下是一個表單的例子。

Name:

Message:

這段代碼描述了一個有兩個輸入字段的表單:較小的輸入字段要求用戶輸入姓名,較大的要求用戶輸入一條消息。當(dāng)點(diǎn)擊發(fā)送按鈕時,表單就提交了,這意味著其字段的內(nèi)容被打包到 HTTP 請求中,并且瀏覽器跳轉(zhuǎn)到該請求的結(jié)果。

當(dāng)

元素的method屬性是GET(或省略)時,表單中的信息將作為查詢字符串添加到action URL 的末尾。 瀏覽器可能會向此 URL 發(fā)出請求:

GET /example/message.html?name=Jean&message=Yes%3F HTTP/1.1

問號表示路徑的末尾和查詢字符串的起始。后面是多個名稱和值,這些名稱和值分別對應(yīng)form輸入字段中的name屬性和這些元素的內(nèi)容。&字符用來分隔不同的名稱對。

在這個 URL 中,經(jīng)過編碼的消息實(shí)際原本是"Yes?",只不過瀏覽器用奇怪的代碼替換了問號。我們必須替換掉請求字符串中的一些字符。使用%3F替換的問號就是其中之一。這樣看,似乎有一個不成文的規(guī)定,每種格式都會有自己的轉(zhuǎn)義字符。這里的編碼格式叫作 URL 編碼,使用一個百分號和16進(jìn)制的數(shù)字來對字符進(jìn)行編碼。在這個例子中,3F(十進(jìn)制為 63)是問號字符的編碼。JavaScript 提供了encodeURIComponentdecodeURIComponent函數(shù)來按照這種格式進(jìn)行編碼和解碼。

console.log(encodeURIComponent("Yes?"));
// → Yes%3F
console.log(decodeURIComponent("Yes%3F"));
// → Yes?

如果我們將本例 HTML 表單中的method屬性更改為POST,則瀏覽器會使用POST方法發(fā)送該表單,并將請求字符串放到請求正文中,而不是添加到 URL 中。

POST /example/message.html HTTP/1.1
Content-length: 24
Content-type: application/x-www-form-urlencoded

name=Jean&message=Yes%3F

GET請求應(yīng)該用于沒有副作用的請求,而僅僅是詢問信息。 可以改變服務(wù)器上的某些內(nèi)容的請求,例如創(chuàng)建一個新帳戶或發(fā)布消息,應(yīng)該用其他方法表示,例如POST。 諸如瀏覽器之類的客戶端軟件,知道它不應(yīng)該盲目地發(fā)出POST請求,但通常會隱式地發(fā)出GET請求 - 例如預(yù)先獲取一個它認(rèn)為用戶很快需要的資源。

我們將在本章后面的回到表單,以及如何與 JavaScript 交互。

Fetch

瀏覽器 JavaScript 可以通過fetch接口生成 HTTP 請求。 由于它比較新,所以它很方便地使用了Promise(這在瀏覽器接口中很少見)。

fetch("example/data.txt").then(response => {
  console.log(response.status);
  // → 200
  console.log(response.headers.get("Content-Type"));
  // → text/plain
});

調(diào)用fetch返回一個Promise,它解析為一個Response對象,該對象包含服務(wù)器響應(yīng)的信息,例如狀態(tài)碼和協(xié)議頭。 協(xié)議頭被封裝在類Map的對象中,該對象不區(qū)分鍵(協(xié)議頭名稱)的大小寫,因?yàn)閰f(xié)議頭名稱不應(yīng)區(qū)分大小寫。 這意味著header.get("Content-Type")headers.get("content-TYPE")將返回相同的值。

請注意,即使服務(wù)器使用錯誤代碼進(jìn)行響應(yīng),由fetch返回的Promise也會成功解析。 如果存在網(wǎng)絡(luò)錯誤或找不到請求的服務(wù)器,它也可能被拒絕。

fetch的第一個參數(shù)是請求的 URL。 當(dāng)該 URL 不以協(xié)議名稱(例如http:)開頭時,它被視為相對路徑,這意味著它解釋為相對于當(dāng)前文檔的路徑。 當(dāng)它以斜線(/)開始時,它將替換當(dāng)前路徑,即服務(wù)器名稱后面的部分。 否則,當(dāng)前路徑直到并包括最后一個斜杠的部分,放在相對 URL 前面。

為了獲取響應(yīng)的實(shí)際內(nèi)容,可以使用其text方法。 由于初始Promise在收到響應(yīng)頭文件后立即解析,并且讀取響應(yīng)正文可能需要一段時間,這又會返回一個Promise

fetch("example/data.txt")
  .then(resp => resp.text())
  .then(text => console.log(text));
// → This is the content of data.txt

有一種類似的方法,名為json,它返回一個Promise,它將解析為,將正文解析為 JSON 時得到的值,或者不是有效的 JSON,則被拒絕。

默認(rèn)情況下,fetch使用GET方法發(fā)出請求,并且不包含請求正文。 你可以通過傳遞一個帶有額外選項(xiàng)的對象作為第二個參數(shù),來進(jìn)行不同的配置。 例如,這個請求試圖刪除example/data.txt

fetch("example/data.txt", {method: "DELETE"}).then(resp => {
  console.log(resp.status);
  // → 405
});

405 狀態(tài)碼意味著“方法不允許”,這是 HTTP 服務(wù)器說“我不能這樣做”的方式。

為了添加一個請求正文,你可以包含body選項(xiàng)。 為了設(shè)置標(biāo)題,存在headers選項(xiàng)。 例如,這個請求包含Range協(xié)議,它指示服務(wù)器只返回一部分響應(yīng)。

fetch("example/data.txt", {headers: {Range: "bytes=8-19"}})
  .then(resp => resp.text())
  .then(console.log);
// → the content

瀏覽器將自動添加一些請求頭,例如Host和服務(wù)器需要的協(xié)議頭,來確定正文的大小。 但是對于包含認(rèn)證信息或告訴服務(wù)器想要接收的文件格式,添加自己的協(xié)議頭通常很有用。

HTTP 沙箱

在網(wǎng)頁腳本中發(fā)出 HTTP 請求,再次引發(fā)了安全性的擔(dān)憂。 控制腳本的人的興趣可能不同于正在運(yùn)行的計算機(jī)的所有者。 更具體地說,如果我訪問themafia.org,我不希望其腳本能夠使用來自我的瀏覽器的身份向mybank.com發(fā)出請求,并且下令將我所有的錢轉(zhuǎn)移到某個隨機(jī)帳戶。

出于這個原因,瀏覽器通過禁止腳本向其他域(如themafia.orgmybank.com等名稱)發(fā)送 HTTP 請求來保護(hù)我們。

在構(gòu)建希望因合法原因訪問多個域的系統(tǒng)時,這可能是一個惱人的問題。 幸運(yùn)的是,服務(wù)器可以在響應(yīng)中包含這樣的協(xié)議頭,來明確地向?yàn)g覽器表明,請求可以來自另一個域:

Access-Control-Allow-Origin: *
運(yùn)用 HTTP

當(dāng)構(gòu)建一個需要讓瀏覽器(客戶端)的 JavaScript 程序和服務(wù)器端的程序進(jìn)行通信的系統(tǒng)時,有一些不同的方式可以實(shí)現(xiàn)這個功能。

一個常用的方法是遠(yuǎn)程過程調(diào)用,通信遵從正常的方法調(diào)用方式,不過調(diào)用的方法實(shí)際運(yùn)行在另一臺機(jī)器中。調(diào)用包括向服務(wù)器發(fā)送包含方法名和參數(shù)的請求。響應(yīng)的結(jié)果則包括函數(shù)的返回值。

當(dāng)考慮遠(yuǎn)程過程調(diào)用時,HTTP 只是通信的載體,并且你很可能會寫一個抽象層來隱藏細(xì)節(jié)。

另一個方法是使用一些資源和 HTTP 方法來建立自己的通信。不同于遠(yuǎn)程調(diào)用方法addUser,你需要發(fā)送一個PUT請求到users/larry,不同于將用戶屬性進(jìn)行編碼后作為參數(shù)傳遞,你定義了一個 JSON 文檔格式(或使用一種已有的格式)來展示一個用戶。PUT請求的正文則只是這樣的一個用來建立新資源的文檔。由GET方法獲取的資源則是自愿的 URL(例如,/users/larry),該 URL 返回代表這個資源的文檔。

第二種方法使用了 HTTP 的一些特性,所以使得整體更簡潔。例如對于資源緩存的支持(在客戶端存一份副本用于快速訪問)。HTTP 中使用的概念設(shè)計良好,可以提供一組有用的原則來設(shè)計服務(wù)器接口。

安全和 HTTPS

通過互聯(lián)網(wǎng)傳播的數(shù)據(jù),往往走過漫長而危險的道路。 為了到達(dá)目的地,它必須跳過任何東西,從咖啡店的 Wi-Fi 到由各個公司和國家管理的網(wǎng)絡(luò)。 在它的路線上的任何位置,它都可能被探測或者甚至被修改。

如果對某件事保密是重要的,例如你的電子郵件帳戶的密碼,或者它到達(dá)目的地而未經(jīng)修改是重要的,例如帳戶號碼,你使用它在銀行網(wǎng)站上轉(zhuǎn)賬,純 HTTP 就不夠好了。

安全的 HTTP 協(xié)議,其 URL 以https://開頭,是一種難以閱讀和篡改的,HTTP 流量的封裝方式。 在交換數(shù)據(jù)之前,客戶端證實(shí)該服務(wù)器是它所聲稱的東西,通過要求它證明,它具有由瀏覽器承認(rèn)的證書機(jī)構(gòu)所頒發(fā)的證書。 接下來,通過連接傳輸?shù)乃袛?shù)據(jù),都將以某種方式加密,它應(yīng)該防止竊聽和篡改。

因此,當(dāng) HTTPS 正常工作時,它可以阻止某人冒充你想要與之通話的網(wǎng)站,以及某人窺探你的通信。 這并不完美,由于偽造或被盜的證書和損壞的軟件,存在各種 HTTPS 失敗的事故,但它比純 HTTP 更安全。

表單字段

表單最初是為 JavaScript 之前的網(wǎng)頁設(shè)計的,允許網(wǎng)站通過 HTTP 請求發(fā)送用戶提交的信息。 這種設(shè)計假定與服務(wù)器的交互,總是通過導(dǎo)航到新頁面實(shí)現(xiàn)。

但是它們的元素是 DOM 的一部分,就像頁面的其他部分一樣,并且表示表單字段的 DOM 元素,支持許多其他元素上不存在的屬性和事件。 這些使其可以使用 JavaScript 程序檢查和控制這些輸入字段,以及可以執(zhí)行一些操作,例如向表單添加新功能,或在 JavaScript 應(yīng)用程序中使用表單和字段作為積木。

一個網(wǎng)頁表單在其標(biāo)簽中包含若干個輸入字段。HTML 允許多個的不同風(fēng)格的輸入字段,從簡單的開關(guān)選擇框到下拉菜單和進(jìn)行輸入的字段。本書不會全面的討論每一個輸入字段類型,不過我們會先大概講述一下。

很多字段類型都使用標(biāo)簽。標(biāo)簽的type屬性用來選擇字段的種類,下面是一些常用的類型。

text:一個單行的文本輸入框。

password:和text相同但隱藏了輸入內(nèi)容。

checkbox:一個復(fù)選框。

radio:一個多選擇字段中的一個單選框。

file:允許用戶從本機(jī)選擇文件上傳。

表單字段并不一定要出現(xiàn)在標(biāo)簽中。你可以把表單字段放置在一個頁面的任何地方。但這樣不帶表單的字段不能被提交(一個完整的表單才可以),當(dāng)需要和 JavaScript 進(jìn)行響應(yīng)時,我們通常也不希望按常規(guī)的方式提交表單。

(text)

(password)

(checkbox)

(radio)

(file)

這些元素的 JavaScript 接口和元素類型不同。

多行文本輸入框有其自己的標(biāo)簽結(jié)束標(biāo)簽并使用標(biāo)簽之間的文本作為初始值,而不是使用value屬性存儲文本。

當(dāng)一個表單字段中的內(nèi)容更改時會觸發(fā)change事件。

聚焦

不同于 HTML 文檔中的其他元素,表單字段可以獲取鍵盤焦點(diǎn)。當(dāng)點(diǎn)擊或以某種方式激活時,他們會成為激活的元素,并接受鍵盤的輸入。

因此,只有獲得焦點(diǎn)時,你才能輸入文本字段。 其他字段對鍵盤事件的響應(yīng)不同。 例如,

對于一些頁面,用戶希望立刻使用到一個表單字段。JavaScript 可以在頁面載入完成時將焦點(diǎn)放到這些字段上,HTML 提供了autofocus屬性,可以實(shí)現(xiàn)相同的效果,并讓瀏覽器知道我們正在嘗試實(shí)現(xiàn)的事情。這向?yàn)g覽器提供了選項(xiàng),來禁用一些錯誤的操作,例如用戶希望將焦點(diǎn)置于其他地方。

瀏覽器也允許用戶通過 TAB 鍵來切換焦點(diǎn)。通過tabindex屬性可以改變元素接受焦點(diǎn)的順序。后面的例子會讓焦點(diǎn)從文本輸入框跳轉(zhuǎn)到 OK 按鈕而不是到幫助鏈接。

 (help)

默認(rèn)情況下,多數(shù)的 HTML 元素不能擁有焦點(diǎn)。但是可以通過添加tabindex屬性使任何元素可聚焦。tabindex為 -1 使 TAB 鍵跳過元素,即使它通常是可聚焦的。

禁用字段

所有的表單字段都可以通過其disable屬性來禁用。它是一個可以被指定為沒有值的屬性 - 事實(shí)上它出現(xiàn)在所有禁用的元素中。


禁用的字段不能擁有焦點(diǎn)或更改,瀏覽器使它們變成灰色。

當(dāng)一個程序在處理一些由按鍵或其他控制方式出發(fā)的事件,并且這些事件可能要求和服務(wù)器的通信時,將元素禁用直到動作完成可能是一個很好的方法。按照這用方式,當(dāng)用戶失去耐心并且再次點(diǎn)擊時,不會意外的重復(fù)這一動作。

作為整體的表單

當(dāng)一個字段被包含在元素中時,其 DOM 元素會有一個form屬性指向form的 DOM 元素。元素則會有一個叫作elements屬性,包含一個類似于數(shù)據(jù)的集合,其中包含全部的字段。

一個表單字段的name屬性會決定在form提交時其內(nèi)容的辨別方式。同時在獲取formelements屬性時也可以作為一種屬性名,所以elements屬性既可以像數(shù)組(由編號來訪問)一樣使用也可以像映射一樣訪問(通過名字訪問)。


  Name: 
Password:

type屬性為submit的按鈕在點(diǎn)擊時,會提交表單。在一個form擁有焦點(diǎn)時,點(diǎn)擊enter鍵也會有同樣的效果。

通常在提交一個表單時,瀏覽器會將頁面導(dǎo)航到formaction屬性指明的頁面,使用GETPOST請求。但是在這些發(fā)生之前,"submit"事件會被觸發(fā)。這個事件可以由 JavaScript 處理,并且處理器可以通過調(diào)用事件對象的preventDefault來禁用默認(rèn)行為。

Value:

在 JavaScript 中submit事件有多種用途。我們可以編寫代碼來檢測用戶輸入是否正確并且立刻提示錯誤信息,而不是提交表單。或者我們可以禁用正常的提交方式,正如這個例子中,讓我們的程序處理輸入,可能使用fetch將其發(fā)送到服務(wù)器而不重新加載頁面。

文本字段

type屬性為textpassword標(biāo)簽和textarea標(biāo)簽組成的字段有相同的接口。其 DOM 元素都有一個value屬性,保存了為字符串格式的當(dāng)前內(nèi)容。將這個屬性更改為另一個值將改變字段的內(nèi)容。

文本字段selectionStartselectEnd屬性包含光標(biāo)和所選文字的信息。當(dāng)沒有選中文字時,這兩個屬性的值相同,表明當(dāng)前光標(biāo)的信息。例如,0 表示文本的開始,10 表示光標(biāo)在第十個字符之后。當(dāng)一部分字段被選中時,這兩個屬性值會不同,表明選中文字開始位置和結(jié)束位置。

和正常的值一樣,這些屬性也可以被更改。

想象你正在編寫關(guān)于 Knaseknemwy 的文章,但是名字拼寫有一些問題,后續(xù)代碼將

replaceSelection函數(shù)用給定的字符串替換當(dāng)前選中的文本字段內(nèi)容,并將光標(biāo)移動到替換內(nèi)容后讓用戶可以繼續(xù)輸入。change事件不會在每次有輸入時都被調(diào)用,而是在內(nèi)容在改變并失焦后觸發(fā)。為了及時的響應(yīng)文本字段的改變,則需要為input事件注冊一個處理器,每當(dāng)用戶有輸入或更改時就被觸發(fā)。

下面的例子展示一個文本字段和一個展示字段中的文字的當(dāng)前長度的計數(shù)器。

 length: 0
選擇框和單選框

一個選擇框只是一個雙選切換。其值可以通過其包含一個布爾值的checked屬性來獲取和更改。


標(biāo)簽關(guān)聯(lián)部分文本和一個輸入字段。點(diǎn)擊標(biāo)簽上的任何位置將激活該字段,這樣會將其聚焦,并當(dāng)它為復(fù)選框或單選按鈕時切換它的值。

單選框和選擇框類似,不過單選框可以通過相同的name屬性,隱式關(guān)聯(lián)其他幾個單選框,保證只能選擇其中一個。

Color:



提供給querySelectorAll的 CSS 查詢中的方括號用于匹配屬性。 它選擇name屬性為"color"的元素。

選擇字段

選擇字段和單選按鈕比較相似,允許用戶從多個選項(xiàng)中選擇。但是,單選框的展示排版是由我們控制的,而標(biāo)簽將允許用戶選擇任意數(shù)量的選項(xiàng),而不僅僅是一個選項(xiàng)。 在大多數(shù)瀏覽器中,這會顯示與正常的選擇字段不同的效果,后者通常顯示為下拉控件,僅在你打開它時才顯示選項(xiàng)。

每一個選項(xiàng)會有一個值,這個值可以通過value屬性來定義。如果沒有提供,選項(xiàng)內(nèi)的文本將作為其值。字段的標(biāo)簽可以通過一個類似于數(shù)組對象的options屬性訪問到。每個選項(xiàng)會有一個叫作selected的屬性,來表明這個選項(xiàng)當(dāng)前是否被選中。這個屬性可以用來被設(shè)定選中或不選中。

這個例子會從多選字段中取出選中的數(shù)值,并使用這些數(shù)值構(gòu)造一個二進(jìn)制數(shù)字。按住CTRL(或 Mac 的COMMAND鍵)來選擇多個選項(xiàng)。

 = 0
文件字段

文件字段最初是用于通過表單來上傳從瀏覽器機(jī)器中獲取的文件。在現(xiàn)代瀏覽器中,也可以從 JavaScript 程序中讀取文件。該字段則作為一個看門人角色。腳本不能簡單地直接從用戶的電腦中讀取文件,但是如果用戶在這個字段中選擇了一個文件,瀏覽器會將這個行為解釋為腳本,便可以訪問該文件。

一個文本字段是一個類似于“選擇文件”或“瀏覽”標(biāo)簽的按鈕,后面跟著所選文件的信息。


文本字段的files屬性是一個類數(shù)組對象(當(dāng)然,不是一個真正的數(shù)組),包含在字段中所選擇的文件。開始時是空的。因此文本字段屬性不僅僅是file屬性。有時文本字段可以上傳多個文件,這使得同時選擇多個文件變?yōu)榭赡堋?/p>

files對象中的對象有name(文件名)、size(文件大小,單位為字節(jié)),和type(文件的媒體類型,如text/plainimage/jpeg)等屬性。

files屬性中不包含文件內(nèi)容的屬性。獲取這個內(nèi)容會比較復(fù)雜。由于從硬盤中讀取文件會需要一些時間,接口必須是異步的,來避免文檔的無響應(yīng)問題。


讀取文件是通過FileReader對象實(shí)現(xiàn)的,注冊一個load事件處理器,然后調(diào)用readAsText方法,傳入我們希望讀取的文件,一旦載入完成,readerresult屬性內(nèi)容就是文件內(nèi)容。

FileReader對象還會在讀取文件失敗時觸發(fā)error事件。錯誤對象本身會存在readererror屬性中。這個接口是在Promise成為語言的一部分之前設(shè)計的。 你可以把它包裝在Promise中,像這樣:

function readFileText(file) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.addEventListener(
      "load", () => resolve(reader.result));
    reader.addEventListener(
      "error", () => reject(reader.error));
    });
    reader.readAsText(file);
  });
}
客戶端保存數(shù)據(jù)

采用 JavaScript 代碼的簡單 HTML 頁面可以作為實(shí)現(xiàn)一些小應(yīng)用的很好的途徑。可以采用小的幫助程序來自動化一些基本的任務(wù)。通過關(guān)聯(lián)一些表單字段和事件處理器,你可以實(shí)現(xiàn)華氏度與攝氏度的轉(zhuǎn)換。也可以實(shí)現(xiàn)由主密碼和網(wǎng)站名來生成密碼等各種任務(wù)。

當(dāng)一個應(yīng)用需要存儲一些東西以便于跨對話使用時,則不能使用 JavaScript 綁定因?yàn)槊慨?dāng)頁面關(guān)閉時這些值就會丟失。你可以搭建一個服務(wù)器,連接到因特網(wǎng),將一些服務(wù)數(shù)據(jù)存儲到其中。在第20章中將會介紹如何實(shí)現(xiàn)這些,當(dāng)然這需要很多的工作,也有一定的復(fù)雜度。有時只要將數(shù)據(jù)存儲在瀏覽器中即可。

localStorage對象可以用于保存數(shù)據(jù),它在頁面重新加載后還存在。這個對象允許你將字符串存儲在某個名字(也是字符串)下,下面是具體示例。

localStorage.setItem("username", "marijn");
console.log(localStorage.getItem("username"));
// → marijn
localStorage.removeItem("username");

一個在localStorage中的值會保留到其被重寫時,它也可以通過removeItem來清除,或者由用戶清除本地數(shù)據(jù)。

不同字段名的站點(diǎn)的數(shù)據(jù)會存在不同的地方。這也表明原則上由localStorage存儲的數(shù)據(jù)只可以由相同站點(diǎn)的腳本編輯。

瀏覽器的確限制一個站點(diǎn)可以存儲的localStorage的數(shù)據(jù)大小。這種限制,以及用垃圾填滿人們的硬盤并不是真正有利可圖的事實(shí),防止該特性占用太多空間。

下面的代碼實(shí)現(xiàn)了一個粗糙的筆記應(yīng)用。程序?qū)⒂脩舻墓P記保存為一個對象,將筆記的標(biāo)題和內(nèi)容字符串相關(guān)聯(lián)。對象被編碼為 JSON 格式并存儲在localStorage中。用戶可以從

腳本從存儲在localStorage中的"Notes"值來獲取它的初始狀態(tài),如果其中沒有值,它會創(chuàng)建示例狀態(tài),僅僅帶有一個購物列表。從localStorage中讀取不存在的字段會返回null

setState方法確保 DOM 顯示給定的狀態(tài),并將新狀態(tài)存儲到localStorage。 事件處理器調(diào)用這個函數(shù)來移動到一個新狀態(tài)。

在這個例子中使用Object.assign,是為了創(chuàng)建一個新的對象,它是舊的state.notes的一個克隆,但是添加或覆蓋了一個屬性。 Object.assign選取第一個參數(shù),向其添加所有更多參數(shù)的所有屬性。 因此,向它提供一個空對象會使它填充一個新對象。 第三個參數(shù)中的方括號表示法,用于創(chuàng)建名稱基于某個動態(tài)值的屬性。

還有另一個和localStorage很相似的對象叫作sessionStorage。這兩個對象之間的區(qū)別在于sessionStorage的內(nèi)容會在每次會話結(jié)束時丟失,而對于多數(shù)瀏覽器來說,會話會在瀏覽器關(guān)閉時結(jié)束。

本章小結(jié)

在本章中,我們討論了 HTTP 協(xié)議的工作原理。 客戶端發(fā)送一個請求,該請求包含一個方法(通常是GET)和一個標(biāo)識資源的路徑。 然后服務(wù)器決定如何處理請求,并用狀態(tài)碼和響應(yīng)正文進(jìn)行響應(yīng)。 請求和響應(yīng)都可能包含提供附加信息的協(xié)議頭。

瀏覽器 JavaScript 可以通過fetch接口生成 HTTP 請求。 像這樣生成請求:

fetch("/18_http.html").then(r => r.text()).then(text => {
  console.log(`The page starts with ${text.slice(0, 15)}`);
});

瀏覽器生成GET請求來獲取顯示網(wǎng)頁所需的資源。 頁面也可能包含表單,這些表單允許在提交表單時,用戶輸入的信息發(fā)送為新頁面的請求。

HTML可以表示多種表單字段,例如文本字段、選擇框、多選字段和文件選取。

這些字段可以用 JavaScript 進(jìn)行控制和讀取。內(nèi)容改變時會觸發(fā)change事件,文本有輸入時會觸發(fā)input事件,鍵盤獲得焦點(diǎn)時觸發(fā)鍵盤事件。 例如"value"(用于文本和選擇字段)或"checked"(用于復(fù)選框和單選按鈕)的屬性,用于讀取或設(shè)置字段的內(nèi)容。

當(dāng)一個表單被提交時,會觸發(fā)其submit事件,JavaScript 處理器可以通過調(diào)用preventDefault來禁用默認(rèn)的提交事件。表單字段的元素不一定需要被包裝在

標(biāo)簽中。

當(dāng)用戶在一個文件選擇字段中選擇了本機(jī)中的一個文件時,可以用FileReader接口來在 JavaScript 中獲取文件內(nèi)容。

localStoragesessionStorage對象可以用來保存頁面重載后依舊保留的信息。第一個會永久保留數(shù)據(jù)(直到用戶決定清除),第二個則會保存到瀏覽器關(guān)閉時。

習(xí)題 內(nèi)容協(xié)商

HTTP 可以做的事情之一就是內(nèi)容協(xié)商。 Accept請求頭用于告訴服務(wù)器,客戶端想要獲得什么類型的文檔。 許多服務(wù)器忽略這個協(xié)議頭,但是當(dāng)一個服務(wù)器知道各種編碼資源的方式時,它可以查看這個協(xié)議頭,并發(fā)送客戶端首選的格式。

URL eloquentjavascript.net/author配置為響應(yīng)明文,HTML 或 JSON,具體取決于客戶端要求的內(nèi)容。 這些格式由標(biāo)準(zhǔn)化的媒體類型"text/plain""text/html""application/json"標(biāo)識。

發(fā)送請求來獲取此資源的所有三種格式。 使用傳遞給fetchoptions對象中的headers屬性,將名為Accept的協(xié)議頭設(shè)置為所需的媒體類型。

最后,請嘗試請求媒體類型"application/rainbows+unicorns",并查看產(chǎn)生的狀態(tài)碼。

// Your code here.
JavaScript 工作臺

構(gòu)建一個接口,允許用戶輸入和運(yùn)行一段 JavaScript 代碼。




Conway 的生命游戲

Conway 的生命游戲是一個簡單的在網(wǎng)格中模擬生命的游戲,每一個細(xì)胞都可以生存或滅亡。對于每一代(回合),都要遵循以下規(guī)則:

任何細(xì)胞,周圍有少于兩個或多于三個的活著的鄰居,都會死亡。

任意細(xì)胞,擁有兩個或三個的活著的鄰居,可以生存到下一代。

任何死去的細(xì)胞,周圍有三個活著的鄰居,可以再次復(fù)活。

任意一個相連的細(xì)胞都可以稱為鄰居,包括對角相連。

注意這些規(guī)則要立刻應(yīng)用于整個網(wǎng)格,而不是一次一個網(wǎng)格。這表明鄰居的數(shù)目由開始的一代決定,并且鄰居在每一代時發(fā)生的變化不應(yīng)該影響給定細(xì)胞新的狀態(tài)。

使用任何一個你認(rèn)為合適的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)這個游戲。使用Math.random來隨機(jī)的生成開始狀態(tài)。將其展示為一個選擇框組成的網(wǎng)格和一個生成下一代的按鈕。當(dāng)用戶選中或取消選中一個選擇框時,其變化應(yīng)該影響下一代的計算。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105045.html

相關(guān)文章

  • JavaScript 編程精解 中文三版 零、前言

    摘要:來源編程精解中文第三版翻譯項(xiàng)目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯部分參考了編程精解第版,這是一本關(guān)于指導(dǎo)電腦的書。在可控的范圍內(nèi)編寫程序是編程過程中首要解決的問題。我們可以用中文來描述這些指令將數(shù)字存儲在內(nèi)存地址中的位置。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地...

    sanyang 評論0 收藏0
  • JavaScript 編程精解 中文三版 十三、瀏覽器中的 JavaScript

    摘要:在本例中,使用屬性指定鏈接的目標(biāo),其中表示超文本鏈接。您應(yīng)該認(rèn)為和元數(shù)據(jù)隱式出現(xiàn)在示例中,即使它們沒有實(shí)際顯示在文本中。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:JavaScript and the Browser 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)》 ...

    zhiwei 評論0 收藏0
  • JavaScript 編程精解 中文三版 二十、Node.js

    摘要:在這樣的程序中,異步編程通常是有幫助的。最初是為了使異步編程簡單方便而設(shè)計的。在年設(shè)計時,人們已經(jīng)在瀏覽器中進(jìn)行基于回調(diào)的編程,所以該語言的社區(qū)用于異步編程風(fēng)格。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Node.js 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)...

    qqlcbb 評論0 收藏0
  • JavaScript 編程精解 中文三版 十五、處理事件

    摘要:事件與節(jié)點(diǎn)每個瀏覽器事件處理器被注冊在上下文中。事件對象雖然目前為止我們忽略了它,事件處理器函數(shù)作為對象傳遞事件對象。若事件處理器不希望執(zhí)行默認(rèn)行為通常是因?yàn)橐呀?jīng)處理了該事件,會調(diào)用事件對象的方法。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Handling Events 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分...

    Clect 評論0 收藏0
  • JavaScript 編程精解 中文三版 十九、項(xiàng)目:像素藝術(shù)編輯器

    摘要:相反,當(dāng)響應(yīng)指針事件時,它會調(diào)用創(chuàng)建它的代碼提供的回調(diào)函數(shù),該函數(shù)將處理應(yīng)用的特定部分。回調(diào)函數(shù)可能會返回另一個回調(diào)函數(shù),以便在按下按鈕并且將指針移動到另一個像素時得到通知。它們?yōu)榻M件構(gòu)造器的數(shù)組而提供。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Project: A Pixel Art Editor 譯者:飛龍 協(xié)議:CC BY-NC-SA 4...

    Meils 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<