成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

mengera88 / 971人閱讀

摘要:版本號(hào)后面是響應(yīng)狀態(tài),首先是一個(gè)三位的狀態(tài)碼,然后是一個(gè)可讀的字符串。以開頭的狀態(tài)碼表示請(qǐng)求成功。是最著名的狀態(tài)碼了,表示找不到資源。調(diào)用返回一個(gè),它解析為一個(gè)對(duì)象,該對(duì)象包含服務(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ù)器的每個(gè)請(qǐng)求都必須包含理解請(qǐng)求所需的所有信息,并且不能利用服務(wù)器上存儲(chǔ)的任何上下文。

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

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

協(xié)議

當(dāng)你在瀏覽器地址欄中輸入eloquentjavascript.net/18_http.html時(shí),瀏覽器會(huì)首先找到和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ù)器會(huì)通過同一個(gè)鏈接返回如下內(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

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

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

GET /17_http.html HTTP/1.1

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

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

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

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

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

HTTP/1.1 200 OK

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

請(qǐng)求或響應(yīng)的第一行后可能會(huì)有任意個(gè)協(xié)議頭,多個(gè)形如name: value的行表明了和請(qǐng)求或響應(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)文檔的大小和類型。在這個(gè)例子中,響應(yīng)是一個(gè) 65585 字節(jié)的 HTML 文檔,同時(shí)也說明了該文檔最后的更改時(shí)間。

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

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

瀏覽器和 HTTP

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

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

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

Name:

Message:

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

當(dāng)

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

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

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

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

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

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

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

name=Jean&message=Yes%3F

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

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

Fetch

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

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

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

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

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

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

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

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

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

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

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

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

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

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

HTTP 沙箱

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

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

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

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

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

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

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

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

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

安全和 HTTPS

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

如果對(duì)某件事保密是重要的,例如你的電子郵件帳戶的密碼,或者它到達(dá)目的地而未經(jīng)修改是重要的,例如帳戶號(hào)碼,你使用它在銀行網(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 正常工作時(shí),它可以阻止某人冒充你想要與之通話的網(wǎng)站,以及某人窺探你的通信。 這并不完美,由于偽造或被盜的證書和損壞的軟件,存在各種 HTTPS 失敗的事故,但它比純 HTTP 更安全。

表單字段

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

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

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

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

text:一個(gè)單行的文本輸入框。

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

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

radio:一個(gè)多選擇字段中的一個(gè)單選框。

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

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

(text)

(password)

(checkbox)

(radio)

(file)

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

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

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

聚焦

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

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

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

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

 (help)

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

禁用字段

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


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

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

作為整體的表單

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

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


  Name: 
Password:

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

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

Value:

在 JavaScript 中submit事件有多種用途。我們可以編寫代碼來檢測(cè)用戶輸入是否正確并且立刻提示錯(cuò)誤信息,而不是提交表單?;蛘呶覀兛梢越谜5奶峤环绞?,正如這個(gè)例子中,讓我們的程序處理輸入,可能使用fetch將其發(fā)送到服務(wù)器而不重新加載頁面。

文本字段

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

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

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

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

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

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

 length: 0
選擇框和單選框

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


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

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

Color:



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

選擇字段

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

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

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

 = 0
文件字段

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

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


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

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

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


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

FileReader對(duì)象還會(huì)在讀取文件失敗時(shí)觸發(fā)error事件。錯(cuò)誤對(duì)象本身會(huì)存在readererror屬性中。這個(gè)接口是在Promise成為語言的一部分之前設(shè)計(jì)的。 你可以把它包裝在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 代碼的簡(jiǎn)單 HTML 頁面可以作為實(shí)現(xiàn)一些小應(yīng)用的很好的途徑??梢圆捎眯〉膸椭绦騺碜詣?dòng)化一些基本的任務(wù)。通過關(guān)聯(lián)一些表單字段和事件處理器,你可以實(shí)現(xiàn)華氏度與攝氏度的轉(zhuǎn)換。也可以實(shí)現(xiàn)由主密碼和網(wǎng)站名來生成密碼等各種任務(wù)。

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

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

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

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

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

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

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

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

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

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

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

本章小結(jié)

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

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

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

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

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

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

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

標(biāo)簽中。

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

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

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

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

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

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

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

// Your code here.
JavaScript 工作臺(tái)

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




Conway 的生命游戲

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

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

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

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

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

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

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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105045.html

相關(guān)文章

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

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

    sanyang 評(píng)論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 評(píng)論0 收藏0
  • JavaScript 編程精解 中文三版 二十、Node.js

    摘要:在這樣的程序中,異步編程通常是有幫助的。最初是為了使異步編程簡(jiǎn)單方便而設(shè)計(jì)的。在年設(shè)計(jì)時(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 評(píng)論0 收藏0
  • JavaScript 編程精解 中文三版 十五、處理事件

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

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

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

    Meils 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<