最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【赫爾辛基大學 全棧開發(fā)01】-Web 應用開發(fā)基礎

2022-04-11 17:39 作者:哥倫布騎士  | 我要投稿

【開發(fā)者控制臺】DevTools Console

Web 開發(fā)第一規(guī)則: 始終在瀏覽器上打開你的開發(fā)者控制臺。 在 macOS 上,按 F12 或者 option-cmd-i 打開控制臺。 Windows 系統(tǒng)或Linux 系統(tǒng),可以按 F12 或 ctrl-shift-i打開控制臺。

記住,開發(fā)web應用時 總是 打開著開發(fā)者控制臺

開發(fā)者控制臺長這樣:

編輯切換為居中

請確保打開 Network 標簽頁,如圖所示,選中 Disable cache 選項。 保存日志(Preserve log)選項也很有用: 它能夠在重新加載頁面時保存應用所打出日志。

雖然在入門介紹中我們常使用網(wǎng)絡(Network)標簽選項,但開發(fā)而言最重要的標簽是控制臺(Console)。

【HTTP GET請求】HTTP GET

服務器和 web 瀏覽器使用 HTTP 協(xié)議相互通信。 “網(wǎng)絡(Network)”選項卡能夠顯示瀏覽器和服務器之間是如何通信的。

當你重新加載頁面(在瀏覽器中按 F5 鍵或者 ? 按鈕) ,控制臺會顯示兩個事件:

  1. 瀏覽器會從服務器中獲取studies.cs.helsinki.fi/exampleapp 頁面的內(nèi)容

  2. 然后下載圖像 kuva.png

編輯切換為居中

在小屏幕上,您可能需要拉大控制臺窗口才能看到這些內(nèi)容。

點擊第一個事件會顯示更多關于本次請求的細節(jié)

編輯切換為居中

上半部分,General 中的內(nèi)容,說明了瀏覽器使用 GET 方法向地址 https://studies.cs.helsinki.fi/exampleapp/ 發(fā)送了一個請求(雖然在截圖的時候還不是這個地址),并且請求成功,因為服務器響應的狀態(tài)碼為 200。

瀏覽器的請求(request)和服務器的響應(response)有一些Headers頭信息:

編輯切換為居中

上面的 響應頭Response headers部分告訴我們一些信息,例如,響應的大小(以字節(jié)為單位)和響應的具體時間。 有個重要的 header Content-Type 告訴我們,響應是utf-8 格式的文本文件,其內(nèi)容已用 HTML 格式化。 通過這種方式,瀏覽器知道響應是一個常規(guī)的 html 頁面,并將它“像一個網(wǎng)頁”一樣渲染到瀏覽器中。

Response 標簽頁展示了響應數(shù)據(jù),這是一個常規(guī)的 html 頁面。 body部分決定了其渲染在屏幕上的頁面結構:

編輯切換為居中

頁面包含一個 div 元素,該元素又包含一個標題、一個指向 notes 頁面的鏈接,以及一個 img 標簽,并顯示了創(chuàng)建 note 的數(shù)量。

由于有一個 img 標簽(src 屬性),瀏覽器會執(zhí)行第二個 http 請求,從服務器獲取圖像 kuva.png。 請求的詳情如下:

編輯切換為居中

這個請求是給地址 https://studies.cs.helsinki.fi/exampleapp/kuva.png 發(fā)送的,它的類型是 HTTP GET。 響應頭告訴我們,響應大小為 89350 字節(jié),其Content-type為 image/png,因此它是一個 png 圖像。 瀏覽器使用這些信息將圖像正確地渲染到屏幕上。

在瀏覽器上打開頁面 https://studies.cs.helsinki.fi/exampleapp/ 所產(chǎn)生的整個調(diào)用鏈條如下:

編輯切換為居中

首先,瀏覽器向服務器發(fā)出 HTTP GET 請求,以獲取頁面的 HTML 代碼。 Html 中的 img 標簽提示瀏覽器還要去獲取圖像 kuva.png。 瀏覽器將 HTML 頁面和圖像渲染到屏幕上。

盡管很難觀察到,但 HTML 頁面在從服務器獲取圖像之前就已經(jīng)開始渲染了。

【傳統(tǒng)的網(wǎng)絡應用】Traditional web applications

示例應用的主頁運作方式與傳統(tǒng)的 web 應用類似。 當進入一個頁面時,瀏覽器會從服務器獲取 HTML 文檔的詳細頁面結構,以及文本內(nèi)容。

服務器以某種方式生成了這個文檔。 這個文檔可能是保存在服務器目錄中的靜態(tài)文本文件(Static File), 也可能是服務器根據(jù)應用的代碼動態(tài)構建的 HTML 文檔(模板填充數(shù)據(jù)),比如,數(shù)據(jù)可能是來自數(shù)據(jù)庫的(MVVM)。

示例應用的 HTML 代碼是動態(tài)的,因為它包含已創(chuàng)建 Note 的數(shù)量信息。

主頁的 HTML 代碼如下所示:

const getFrontPageHtml = noteCount => { ?return ` ? ?<!DOCTYPE html> ? ?<html> ? ? ?<head> ? ? ?</head> ? ? ?<body> ? ? ? ?<div class='container'> ? ? ? ? ?<h1>Full stack example app</h1> ? ? ? ? ?<p>number of notes created ${noteCount}</p> ? ? ?#{此處noteCount就是模板語言中的所謂placeholder占位符} ? ? ? ? ?<a href='/notes'>notes</a> ? ? ? ? ?<img src='kuva.png' width='200' /> ? ? ? ?</div> ? ? ?</body> ? ?</html>`;};app.get('/', (req, res) => { ?const page = getFrontPageHtml(notes.length); ?res.send(page);});

你目前還不需要去理解這些代碼的細節(jié)。

數(shù)據(jù)傳輸具體細節(jié)如下(個人增):

編輯切換為居中

Html 頁面的內(nèi)容被保存為 template 模板字符串,或者說是一個能夠運行的字符串,因為它其中包含有變量($花括號表示變量占位符,不同模板語言有不同規(guī)定)。 在模板字符串中,頁面中動態(tài)更改的那部分內(nèi)容——已保存 Note 的數(shù)量(即代碼中的 noteCount),被動態(tài)地替換為了 Note 的當前數(shù)量(即代碼中的 notes.length)

在代碼中間編寫 HTML 當然不是明智的做法,但對于老派的 PHP 程序員來說,這是一種常規(guī)操作。

在傳統(tǒng)的 web 應用中,瀏覽器是個“憨憨”。 它只會從服務器獲取 HTML 數(shù)據(jù),所有應用的邏輯都在服務器上處理。 服務器中的程序可以是,赫爾辛基大學 Web-palvelinohjelmointi課程中的 Java Spring、也可以是 tietokantasovellus課程中的 Python Flask ,又或者是 Ruby on Rails。

這個樣例使用了 Node.js 中的 Express。(Express是一個簡潔而靈活的node.js Web應用框架, 提供了一系列強大特性幫助你創(chuàng)建各種Web 應用,和豐富的HTTP 工具。 使用Express可以快速地搭建一個完整功能的網(wǎng)站。)

本課程都將會使用 Node.js 和 Express 來創(chuàng)建 Web 服務器。

【在瀏覽器上運行應用邏輯】Running application logic on the browser

保持控制臺打開狀態(tài)。 單擊 ??按鈕清空控制臺。

現(xiàn)在當你進入 notes頁面時,瀏覽器會執(zhí)行 4 個 HTTP 請求:

編輯切換為居中

所有的請求都請求了不同的類型。 第一個請求的類型是 document。 也就是頁面的 HTML 代碼,看起來如下:

編輯切換為居中

當我們比較瀏覽器上顯示的頁面和服務器返回的 HTML 代碼時,我們注意到這些代碼并不包含 Note 列表的數(shù)據(jù)。 Html 的 head部分 包含一個 script 標簽,它會讓瀏覽器去 獲取一個名為 main.js 的 JavaScript 文件。

JavaScript 代碼看起來像這樣:

var xhttp = new XMLHttpRequest();xhttp.onreadystatechange = function() { ?if (this.readyState == 4 && this.status == 200) { ? ?const data = JSON.parse(this.responseText); ? ? // JSON庫解析返回數(shù)據(jù) ? ?console.log(data); ? ?var ul = document.createElement('ul'); ? ? // html頁面中新建一個無序列表元素 ? ?ul.setAttribute('class', 'notes'); ? ? ?// 為新建的無序列表元素設置值為notes 的class 屬性 ? ?data.forEach(function(note) { ? ? ? ? ? ?// 遍歷獲得的數(shù)據(jù) ? ? ?var li = document.createElement('li'); ? ? ?ul.appendChild(li); ? ? ? ? ? ? ? ? // 為我們創(chuàng)建的無序列表元素添加列表項子元素 ? ? ?li.appendChild(document.createTextNode(note.content)); ? // 列表項子元素新增文本值 ? ?}); ? ?// 獲取原h(huán)tml文件中id屬性為notes的div盒子,并將我們上面制作好的ul添加 ? ? ?document.getElementById('notes').appendChild(ul); ? ? }};xhttp.open('GET', '/data.json', true);xhttp.send();

代碼的細節(jié)現(xiàn)在并不重要,穿插一些代碼,是為了增加圖像與文本的趣味性。我們將在第1章正式地開始編碼。 本章節(jié)的示例代碼實際上與本課程所要講的編碼技術毫無關系。

有些人可能想問為什么要使用 xhttp 對象而不是使用現(xiàn)代的獲取方法。 這是因為我們不想引入 promise 的概念,而且代碼在這一章節(jié)只是二等公民。 在第 2 章節(jié)中,我們將回過頭來用更加現(xiàn)代的方式來向服務器發(fā)送請求。

在獲取到 script 標簽后,瀏覽器便立即開始執(zhí)行 script 的代碼。

最后兩行定義了讓瀏覽器對服務器地址 /data.json 執(zhí)行一個 HTTP GET 請求:

xhttp.open('GET', '/data.json', true);xhttp.send();

這是“Network”選項卡上顯示 request 信息的最低要求。

我們可以試著直接通過瀏覽器訪問 https://studies.cs.helsinki.fi/exampleapp/data.json 地址:

編輯切換為居中

在這里我們找到了以 JSON 格式展示的 Note ,這就是Note的 “原始數(shù)據(jù)”。

默認配置下,基于Chrome 的瀏覽器不太擅長顯示 json 格式的數(shù)據(jù)。 可以使用插件來處理 Json 格式。 例如,將 JSONView 安裝到 Chrome,然后重新加載頁面。 數(shù)據(jù)現(xiàn)在可以被更好地格式化展示出來了:

因此,上面 notes 頁面的 JavaScript 代碼會下載包含 Note 列表的的 JSON 數(shù)據(jù),并利用 Note 的內(nèi)容構建出一個符號列表:

構建是通過如下代碼實現(xiàn)的:

const data = JSON.parse(this.responseText);console.log(data);var ul = document.createElement('ul');ul.setAttribute('class', 'notes');data.forEach(function(note) { ?var li = document.createElement('li'); ?ul.appendChild(li); ?li.appendChild(document.createTextNode(note.content));});document.getElementById('notes').appendChild(ul);

代碼首先創(chuàng)建了一個帶有 ul-標簽 的無序列表...

var ul = document.createElement('ul');ul.setAttribute('class', 'notes');

然后再為每個 Note 加上一個 li-標簽。僅將每個 Note 的 content 字段變成了 li-標簽 的內(nèi)容,而原始數(shù)據(jù)的 timestamps 時間戳在這里并沒派上用場。

data.forEach(function(note) { ?var li = document.createElement('li'); ?ul.appendChild(li); ?li.appendChild(document.createTextNode(note.content));});

現(xiàn)在打開控制臺上的 Console 標簽:

編輯切換為居中

通過單擊行首的小三角形,可以展開控制臺上的文本。

編輯切換為居中

控制臺上能輸出內(nèi)容是因為代碼中的 console.log 命令:

const data = JSON.parse(this.responseText);console.log(data);

因此,在從服務器接收到數(shù)據(jù)之后,代碼將其打印到了控制臺。

在整個課程中,你會經(jīng)常用到 Console 選項卡和 Console.log 命令。

【事件處理和回調(diào)函數(shù)】Event handlers and Callback functions

這段代碼的結構有點奇怪:

var xhttp = new XMLHttpRequest();xhttp.onreadystatechange = function() { ?// code that takes care of the server response};xhttp.open('GET', '/data.json', true);xhttp.send();

發(fā)送到服務器的請求放在了最后一行,但是處理響應的代碼卻在上面定義了。這是怎么回事?

xhttp.onreadystatechange = function () {

這一行中,onreadystatechange 這個事件處理程序是定義在 xhttp 對象上的,xhttp對象是用于執(zhí)行請求的。當這個對象的狀態(tài)發(fā)生改變時,瀏覽器調(diào)用了這個事件處理函數(shù)。 這個函數(shù)代碼檢查了 readyState 是否等于 4(它描述了操作已完成的狀態(tài)) ,以及響應的 HTTP 狀態(tài)碼是否為 200。

xhttp.onreadystatechange = function() { ?if (this.readyState == 4 && this.status == 200) { ? ?// code that takes care of the server response ?}};

這種調(diào)用事件處理程序的機制在 JavaScript 中非常常見。 事件處理函數(shù)被稱為回調(diào)函數(shù)(callback functions)。 應用代碼并不直接調(diào)用函數(shù)本身,而是運行時環(huán)境(瀏覽器)會在事件發(fā)生時的適當時間調(diào)用函數(shù)。

【文檔對象模型】Document Object Model or DOM

我們可以將 html 頁面看作隱式樹結構。

html ?head ? ?link ? ?script ?body ? ?div ? ? ?h1 ? ? ?div ? ? ? ?ul ? ? ? ? ?li ? ? ? ? ?li ? ? ? ? ?li ? ? ?form ? ? ? ?input ? ? ? ?input

在控制臺Elements選項卡中可以看到相同的樹狀結構。

瀏覽器的功能就是基于這種,把 HTML元素描述成一棵樹的想法。(元素節(jié)點樹)

文檔對象模型(Document Object Model,DOM)是一個應用編程接口(application Programming Interface,API) ,它支持對 web 頁面對應的元素樹進行編程修改。

上一部分中介紹的 JavaScript 代碼就是使用 DOM-API 向頁面添加 Note 列表。

下面的代碼為變量 ul 創(chuàng)建了一個新節(jié)點,并向其添加一些子節(jié)點:

var ul = document.createElement('ul');data.forEach(function(note) { ?var li = document.createElement('li'); ?ul.appendChild(li); ?li.appendChild(document.createTextNode(note.content));});

最后,ul 變量的樹分支被接到了整個頁面的 HTML 樹中的適當位置:

document.getElementById('notes').appendChild(ul);

【從控制臺中操作文檔對象】Manipulating the document-object from console

Html 文檔 DOM 樹的最頂層節(jié)點稱為文檔document 對象。 我們可以使用 DOM-API 在網(wǎng)頁上執(zhí)行各種操作。 您可以通過在控制臺中鍵入 document 來訪問文檔對象:

讓我們從控制臺向頁面添加一個新的 Note。

首先,我們從頁面中獲得 Note 列表,該列表位于頁面的第一個 ul 元素中:

編輯切換為居中

list = document.getElementsByTagName('ul')[0];

然后創(chuàng)建一個新的 li 元素并添加一些文本內(nèi)容:

newElement = document.createElement('li');newElement.textContent = 'Page manipulation from console is easy';

并將新的 li 元素添加到列表中:

list.appendChild(newElement);

編輯切換為居中

雖然頁面在瀏覽器上被更新了,這些更改不是永久性的。 如果頁面重新加載,新的 Note 就消失了,因為更改并沒有推送到服務器。 瀏覽器獲取的 JavaScript 代碼會總是基于 https://studies.cs.helsinki.fi/exampleapp/data.json 的 JSON 數(shù)據(jù)來創(chuàng)建 Note 列表。

【CSS】

Notes 頁面的 HTML 代碼中 head 元素包含了一個 link 標簽,該標簽確定瀏覽器必須從地址 main.css中獲取 CSS 樣式表。

層疊樣式表(Cascading Style Sheets, CSS),是一種用來確定 web 應用外觀的標記語言。

獲取的 css 文件如下所示:

.container { ?padding: 10px; ?border: 1px solid;}.notes { ?color: blue;}

該文件定義了兩個類選擇器 class selectors。 它們用于選擇頁面的某些部分,并對它們定義樣式規(guī)則來裝飾它們。

類選擇器的定義始終以句點開頭,并包含類的名稱。

這些類是屬性attributes,可以添加到 HTML 元素中。

CSS 屬性可以在控制臺的 element 標簽上查看:

編輯切換為居中

最外面的 div 元素有 class 屬性 ,值為 container ,包含 notes 列表的 ul 元素也有 class 屬性 ,名為 notes。

CSS 規(guī)則定義了 container 類的元素,將用一個像素寬的邊框 border勾勒出來。 它還為該元素設置了 10 個像素的填充 padding。 這會在元素內(nèi)容和邊框之間增加一些空白。

第二個 CSS 規(guī)則將文本顏色設置為藍色。

Html 元素也可以有 class 以外的其他屬性。 包含 Note 的 div 元素有一個 id 屬性。 JavaScript 代碼使用 id 來查找元素。

控制臺的Elements選項卡可用于更改元素的樣式。

編輯切換為居中

在控制臺上所做的更改也不是永久性的。 如果要進行持久的更改,必須將更改保存到服務器上的 CSS 樣式表中。

【加載一個包含 JavaScript 的頁面-復習】Loading a page containing JavaScript - review

讓我們復習一下在瀏覽器上打開頁面 https://studies.cs.helsinki.fi/exampleapp/notes 時會發(fā)生什么。

編輯切換為居中

  1. 瀏覽器使用 HTTP GET 請求從服務器獲取定義內(nèi)容和頁面結構的 HTML 代碼

  2. Html 代碼中的 Links 標簽會讓瀏覽器獲取 CSS 樣式表 main.css

  3. 以及 JavaScript 代碼文件 main.js

  4. 瀏覽器執(zhí)行 JavaScript 代碼,代碼向地址[<https://studies.cs.helsinki.fi/exampleapp/data.json>](<https://studies.cs.helsinki.fi/exampleapp/data.json>) 發(fā)出 HTTP GET 請求,請求返回了包含 note 的 JSON 數(shù)據(jù)。

  5. 獲取數(shù)據(jù)后,瀏覽器執(zhí)行一個event handler 事件處理程序, 使用 DOM-API 將 Note 渲染到頁面

【表單與 HTTP POST】Forms and HTTP POST

接下來讓我們看看添加 Note 是如何完成的。

Notes 頁面包含一個 form 元素。

編輯切換為居中

當單擊表單上的按鈕時,瀏覽器將向服務器發(fā)送用戶的輸入。 讓我們打開 Network 標簽頁,看看提交表單時發(fā)生了什么:

很驚奇吧,提交表單總共會導致 5 個 HTTP 請求。

編輯切換為居中

第一個是表單提交事件(submit)。 讓我們放大一下:

編輯切換為居中

它是對服務器 /new_note地址發(fā)送的 HTTP POST請求。 服務器用 HTTP 狀態(tài)碼 302 進行響應。 這是一個URL 重定向,服務器通過這個 URL 重定向,請求瀏覽器執(zhí)行一個新的 HTTP GET 請求,該請求定義在 Header 的 Location (即 /notes 地址)中。

因此,瀏覽器重新加載 Notes 頁面。 重新加載會導致另外三個 HTTP 請求: 獲取樣式表(main.css)、 JavaScript 代碼(main.js)和 notes 的原始數(shù)據(jù)(data.json)。

Network選項卡還顯示了與表單一起提交的表單數(shù)據(jù):

編輯切換為居中

Form 標簽具有屬性 action 和 method,它們定義了將表單作為一個 HTTP POST 請求提交到地址 /new_note。

編輯切換為居中

服務器上負責 POST 請求的代碼很簡單(注意: 此代碼在服務器上,而不是在瀏覽器獲取的 JavaScript 代碼上) :

app.post('/new_note', (req, res) => { ?notes.push({ ? ?content: req.body.note, ? ? // 用戶輸入的內(nèi)容 ? ?date: new Date(), ? ? ? ? ?// 提交時間 ?}); ?return res.redirect('/notes');});

數(shù)據(jù)作為 POST-請求的body發(fā)送到服務器。

服務器可以通過訪問請求對象 req 的 req.body 字段來訪問發(fā)送來的數(shù)據(jù)。

Server 創(chuàng)建一個新的 note 對象,并將其添加到一個名為 notes 的數(shù)組中。

notes.push({ ?content: req.body.note, ?date: new Date(),});

Note 對象包含兩個字段: 包含 Note 實際內(nèi)容的 content,以及包含創(chuàng)建 Note 的日期和時間的 date。 服務器不會將新 Note 保存到數(shù)據(jù)庫中,因此當服務器重新啟動服務時,新的 Note 就會消失。

【AJAX】

應用的 Notes 頁面遵循90年代初期的 web 開發(fā)風格,并且“使用了 Ajax”。 這種技術在當時,2000 年初正處于 web 技術浪潮的頂峰。

AJAX (Asynchronous JavaScript and XML) 是在瀏覽器技術進步的基礎上于 2005 年 2 月引入的一個術語,它描述了一種新的革命性的方法,這種方法使用包含在 HTML 中的 JavaScript 來獲取網(wǎng)頁內(nèi)容,而且不需要重新渲染頁面。(局部修改頁面)

在 AJAX 之前的年代,所有的 web 頁面都像我們在本章前面看到的傳統(tǒng) web 應用一樣工作。 頁面上顯示的所有數(shù)據(jù)都是從服務器生成的 html 代碼獲取的。

Notes 頁面使用了 AJAX 獲取 Notes 數(shù)據(jù)。 提交表單仍然使用傳統(tǒng)的 web 表單提交機制。

應用的 url 反映了過去無憂無慮的時光。 數(shù)據(jù)從 url https://studies.cs.helsinki.fi/exampleapp/data.JSON 中獲取,新的 Note 被發(fā)送到 url https://studies.cs.helsinki.fi/exampleapp/new_note 。 如今,這樣的 url 被認為是不可接受的,因為它們沒有遵循公認的RESTful api 約定,我們將在第三章中進一步研究。

RESTful APImedium.com

現(xiàn)在 AJAX 的存在是如此普遍,以至于人們認為它是理所當然的。 AJAX 這個術語已經(jīng)逐漸被遺忘,“新時代的我們”甚至沒有聽說過它。

【單頁面應用】Single page app

在我們的示例應用中,主頁的工作方式類似于傳統(tǒng)的網(wǎng)頁: 所有的邏輯都在服務器上,瀏覽器只按照指示渲染 HTML。

Notes 頁面為瀏覽器提供了一些職責,為現(xiàn)有的 Note 生成 HTML 代碼。 瀏覽器通過執(zhí)行從服務器獲取的 JavaScript 代碼來處理這個任務。 代碼從服務器以Json格式獲取 Note,并對其添加 HTML 元素,并利用 DOM-API 將 Note 顯示到頁面中。

近年來,創(chuàng)建網(wǎng)絡應用的單頁應用 Single-page application (SPA) 風格出現(xiàn)了。SPA 類型的網(wǎng)站不會像我們的示例應用那樣從服務器上單獨獲取所有頁面,而是只從服務器獲取一個 HTML 頁面,其內(nèi)容由 JavaScript 在瀏覽器中執(zhí)行操作。

我們的應用的 Notes 頁面與 SPA 風格的應用有一些相似之處,但它還沒有完全到位。 盡管顯示Note 的邏輯是在瀏覽器上運行的,但頁面仍然使用傳統(tǒng)的方式添加新Note 。 數(shù)據(jù)通過表單提交發(fā)送到服務器,服務器指示瀏覽器重新加載帶有重定向的 Notes 頁面。

我們示例應用的單頁應用版本可以在 https://studies.cs.helsinki.fi/exampleapp/spa 中找到。 乍一看,這個應用看起來與前一個應用完全相同。 Html 代碼幾乎完全相同,但 JavaScript 文件不同(spa.js) ,form 標簽的定義方式有一個小小的變化:

編輯切換為居中

表單沒有action屬性或method屬性來定義如何以及往哪里發(fā)送輸入數(shù)據(jù)。

打開 Network-選項卡并清空它。 當您現(xiàn)在創(chuàng)建一個新的便箋時,您會注意到瀏覽器只向服務器發(fā)送了一個請求。

Post 請求到地址new_note_spa,包含新 Note 的 JSON 數(shù)據(jù),其中既包含 Note 的內(nèi)容(content) ,也包含時間戳(date) :

{ ?content: "single page app does not reload the whole page", ?date: "2019-05-25T15:15:59.905Z"}

請求的 Content-Type 頭信息告訴服務器,所包含的數(shù)據(jù)是以 JSON 格式表示的。

編輯切換為居中

如果沒有這個頭,服務器將不知道如何正確地解析數(shù)據(jù)。

服務器用創(chuàng)建的狀態(tài)碼201進行響應。 這次服務器沒有請求重定向,瀏覽器會保持在同一頁面上,并且不再發(fā)送 http 請求。

這個應用的 SPA 版本并不以傳統(tǒng)的方式發(fā)送表單數(shù)據(jù),而是使用從服務器獲取的 JavaScript 代碼。 我們將稍微研究一下這段代碼,雖然還沒有必要理解它的所有細節(jié)。

var form = document.getElementById('notes_form');form.onsubmit = function(e) { ?e.preventDefault(); ?var note = { ? ?content: e.target.elements[0].value, ? ?date: new Date(), ?}; ?notes.push(note); ?e.target.elements[0].value = ''; ?redrawNotes(); ?sendToServer(note);};

命令 document.getElementById('notes_form') 指示代碼從頁面中提取 form 元素,并注冊一個事件處理函數(shù)來處理表單提交事件。 事件處理函數(shù)將立即調(diào)用方法 e.preventDefault () ,以防止對表單 submit 的默認處理。 默認處理會將數(shù)據(jù)發(fā)送到服務器并導致重定向(一次新的Get請求),這不是我們的初衷。

然后,事件處理程序創(chuàng)建一個新的 Note,使用命令notes.push(note)將其添加到 Note 列表中,并在頁面上重新渲染了 Note 列表,最終向服務器發(fā)送了新建 Note 的請求。

向服務器發(fā)送 Note 的代碼如下:

var sendToServer = function(note) { ?var xhttpForPost = new XMLHttpRequest(); ?// ... ?xhttpForPost.open('POST', '/new_note_spa', true); ?xhttpForPost.setRequestHeader('Content-type', 'application/json'); ?xhttpForPost.send(JSON.stringify(note));};

代碼確定數(shù)據(jù)是通過 HTTP POST 請求發(fā)送的,數(shù)據(jù)類型是 JSON。 數(shù)據(jù)類型由 Content-type Header 確定。 然后,數(shù)據(jù)以 json 字符串的形式發(fā)送。

應用代碼可以在 https://github.com/mluukkai/example_app 上找到。 值得注意的是,這個應用只是用來演示課程的概念。 該代碼在某種程度上遵循了糟糕的開發(fā)風格,不應該在創(chuàng)建自己的應用時作為示例使用。 使用的 url 也是如此。 發(fā)送新Note 的 URL,即新建Note 的new_note_spa并不遵循當前的最佳實踐。

【JavaScript 庫】JavaScript-libraries

這個示例應用是通過所謂的vanilla JavaScript 來完成的,只使用了 DOM-API 和 JavaScript 來操作頁面的結構。

與僅使用 JavaScript 和 DOM-API 不同,通常會使用比直接操作 DOM-API 更容易的工具庫來操作頁面。 其中一個非常流行的庫就是 jQuery 。

當時,在 web 應用主要遵循服務器生成 HTML 頁面的傳統(tǒng)風格,jQuery 當時是在這種情況下發(fā)展起來的。這種風格的功能通過在瀏覽器端使用 JavaScript 搭配使用 jQuery 來增強。 jQuery 成功的原因之一是它所謂的跨瀏覽器兼容性。 不管是哪家公司的哪個瀏覽器,這個庫都能正常工作,所以不需要特定于瀏覽器的解決方案。 如今,由于 Vanilla JS 的進步,使用 jQuery 已經(jīng)不那么合理了,而且最流行的瀏覽器通常都能很好地支持基本功能。

單頁應用的興起帶來了幾種比 jQuery 更“現(xiàn)代”的網(wǎng)頁開發(fā)方式。 第一波開發(fā)者的最愛是 BackboneJS.。 自 2012 年 launch 以來,谷歌的 AngularJS 幾乎快速成為現(xiàn)代網(wǎng)絡開發(fā)的行業(yè)標準。

然而,自從 Angular 團隊在 2014 年 10 月宣布對第 1 版的支持將結束,Angular 2 將不再向后兼容第一版后,Angular 的受歡迎程度直線下降。 Angular 2 和更新的版本沒有得到太熱烈的歡迎。

目前,實現(xiàn) web 應用瀏覽器端邏輯的最流行的工具是 Facebook 的 React 庫。 在本課程中,我們將熟悉 React 和 Redux 庫,它們經(jīng)常一起使用。

React 的勢頭看起來很猛,但是 JavaScript 的世界是不斷變化的。 例如,最近的一個新秀 VueJS 已經(jīng)引起了一些興趣。

Vue.js 漸進式 JavaScript 框架cn.vuejs.org

【全棧-web 開發(fā)】Full stack web development

這個課程的名字是什么意思?全棧是一個流行詞,每個人都在談論它,但沒有人真正知道它的意思。 或者至少,對于這個術語沒有一致的定義。

幾乎所有的 web 應用都有(至少)兩個“層” : 最接近最終用戶的瀏覽器是最頂層,而服務器是最底層。 在服務器下面通常還有一個數(shù)據(jù)庫層。 因此,我們可以將 web 應用的體系結構看作是一層層的堆棧。

編輯切換為居中

通常,我們也會討論前端frontend 和 后端backend 。 瀏覽器是前端,運行在瀏覽器上的 JavaScript 是前端代碼。 另一方面,服務器是后端。

在本課程的上下文中,全棧 web 開發(fā)意味著我們關注應用的所有部分: 從前端、后端到數(shù)據(jù)庫。 有時候,服務器上的軟件及其操作系統(tǒng)會被看作是全棧的一部分,但我們不會深入討論這部分內(nèi)容。

我們將使用 JavaScript 編寫后端代碼,使用 Node.js 運行時環(huán)境。 在全棧的多個層次上使用相同的編程語言,給全棧 web 開發(fā)提供了一個全新的維度。 然而,對于所有層次的棧,使用相同的編程語言(JavaScript)并不是全棧 web 開發(fā)的必要條件。

過去,對于開發(fā)人員來說,更常見的做法是專注于全棧的某個層,例如后端。 后端和前端的技術棧完全不同。 隨著全棧趨勢的出現(xiàn),對于開發(fā)人員來說,熟練掌握應用和數(shù)據(jù)庫的全棧內(nèi)容已經(jīng)變得非常普遍。 通常情況下,全棧開發(fā)人員還必須有足夠的配置和管理技能來操作他們的應用,例如,上云。(云端部署 deploy to cloud)

【JavaScript 疲勞】JavaScript fatigue

全棧 web 開發(fā)在許多方面都具有挑戰(zhàn)性。 在許多地方會有突發(fā)情況,并且調(diào)試起來比普通桌面應用要困難得多。 JavaScript (與許多其他語言相比) 并不總是像你期望的那樣工作 ,其運行時環(huán)境的異步工作方式帶來了各種各樣的挑戰(zhàn)。 網(wǎng)絡中的通信需要對 http 協(xié)議的知識儲備。 還必須處理數(shù)據(jù)庫、服務器管理和配置。 了解足夠的 CSS 至少在一定程度上能夠使應用顯得好看。

JavaScript 的世界發(fā)展得很快,也帶來了一系列的挑戰(zhàn)。 工具、庫和語言本身都在不斷發(fā)展。 有些人已經(jīng)開始厭倦了這種不斷的變化,并為此創(chuàng)造了一個新詞: JavaScript 疲勞??梢蚤喿xHow to Manage JavaScript Fatigue on auth0 或者 JavaScript fatigue on Medium

在本課程中,您將遭受 JavaScript 疲勞的折磨。 對我們來說幸運的是,有幾種方法可以使學習曲線變得平滑,我們可以從編碼而不是配置開始。 我們不能完全避免配置,但是我們可以在接下來的幾周里愉快地推進,同時避免糟糕的配置地獄。


【赫爾辛基大學 全棧開發(fā)01】-Web 應用開發(fā)基礎的評論 (共 條)

分享到微博請遵守國家法律
德阳市| 庆安县| 罗定市| 昌邑市| 定襄县| 台湾省| 留坝县| 德江县| 唐山市| 会理县| 广州市| 涟水县| 泽库县| 怀集县| 固镇县| 游戏| 河东区| 长泰县| 内丘县| 漳州市| 于田县| 成武县| 积石山| 平江县| 霍州市| 视频| 永州市| 红桥区| 志丹县| 保靖县| 屏东县| 大田县| 英山县| 元朗区| 长岭县| 榆中县| 大名县| 贵德县| 肥乡县| 万宁市| 广河县|