寫一個迷你 Dart 應用
要點有哪些?
- DartPad 讓你不需要 HTML 引用編寫一個簡單的 Dart web 應用。
- 一個 Dart 應用包括 Dart、HTML、和(通常)CSS 代碼。
- 編譯 一個 web 應用的 Dart 代碼為 JavaScript 來在任意現代瀏覽器中運行此應用。
- HTML 文件管理瀏覽器頁面中的 Dart 代碼。
- 樹/節(jié)點的 DOM 結構,模擬瀏覽器頁面。
- 使用帶 ID 的 querySelector() 來從 DOM 獲取元素。
- CSS 選擇器用來選擇匹配 DOM 中的元素。
- 使用 CSS 規(guī)則來給元素添加樣式。
要寫一個 Dart web 應用,你需要明白幾個概念——DOM 樹、節(jié)點、元素、HTML,以及 Dart 語言和庫。
這些概念是相互依賴的,但我們必須從某個地方開始,所以我們從一個簡單的 HTML 文件開始,它介紹了 DOM 樹和節(jié)點。從那里,你構建一個視圖框架,從 Dart 應用剝離動態(tài)生成頁面的代碼。
雖然簡單,但這個例子展示了如何連接 Dart 應用和 HTML 頁面,以及一個 Dart 應用如何與頁面上的元素相互作用。這些概念為更有趣、更有用的 web 應用提供了基礎。
關于 Dart, HTML, 以及 CSS
如果你用過 DartPad,你已經看到了讓你編寫 web 應用代碼的 DART、HTML 和 CSS 標簽。這三個語言分別負責 web 應用的不同方面。
| 語言 | 用途 |
|---|---|
| Dart | 實現 web 應用的交互和動態(tài)行為 |
| HTML | 描述 web 應用頁面的內容(文檔和結構中的元素) |
| CSS | 控制頁面元素的外觀 |
Dart 程序可以響應事件,例如鼠標點擊,動態(tài)地操作 web 頁面上的元素,以及保存信息。在 web 應用被部署之前,Dart 代碼必須被編譯為 JavaScript 代碼。
HTML 是一種描述 web 頁面的語言。它使用標簽設置頁面的初始結構,為頁面添加元素,并為頁面交互嵌入任意腳本。HTML 設置初始的文檔樹,并指定元素類型、CSS 類和 ID,這些允許 HTML、CSS 和 Dart 程序來引用相同的元素。
CSS 表示層疊樣式表(Cascading Style Sheets),描述了文檔中元素的外觀。CSS 控制格式的許多方面,例如:字體、字號、顏色、背景色、邊框、外邊距,以及對齊。
關于 DOM
文檔對象模型(DOM)表示作為節(jié)點樹的 web 文檔的結構。當一個 HTML 文件被瀏覽器加載,瀏覽器解析 HTML 并在一個窗口顯示文檔。下圖展示了一個簡單的 HTML 文件以及在 Chrome 瀏覽器中生成的 web 頁面。

HTML 使用標簽描述文檔。例如,上圖簡單的 HTML 代碼中使用<title>標簽描述頁面的標題,使用<h1>描述一級標題頭,使用<p>描述段落。在 HTML 代碼中的一些標簽,比如<head>和<body>在 web 頁面是不可見的,但對于文檔結構是有用的。
在 DOM 中,document 對象作為 DOM 樹的根(它沒有父節(jié)點)。在 DOM 樹中不同類型的節(jié)點代表文檔中不同類型的對象。例如,DOM 樹包含頁面元素、文本節(jié)點、屬性節(jié)點。下面是上圖中簡單的 HTML 文件的 DOM 樹。

注意這些標簽,比如<p>段落標簽,它代表多個節(jié)點。段落本身是一個元素節(jié)點。段落中的文本是一個文本節(jié)點(有時候,可能是一個包含許多節(jié)點的子樹)。ID 是一個屬性節(jié)點。
除了根節(jié)點,每個節(jié)點在 DOM 樹中只有一個父節(jié)點。每個節(jié)點可以有多個子節(jié)點。
HTML 文件定義了文檔的初始結構。Dart 或 JavaScript 可以通過添加、刪除動態(tài)地修改文檔,并修改 DOM 樹中的節(jié)點。當 DOM 發(fā)生改變,瀏覽器立刻重新渲染窗口。

上圖展示了一小段 Dart 程序,它通過動態(tài)更改一個段落文本來相應地改變 DOM。程序可以添加和刪除節(jié)點,甚至插入整個子節(jié)點樹。
創(chuàng)建一個新的 Dart 應用
- 進入 DartPad。
- 點擊 New Pad 按鈕,撤銷你上次在 DartPad 做的所有更改。
注意:這些 DartPad 的功能隱藏了一些 HTML 引用代碼。如果你想要使用任何其它的編輯器,我們推薦從一個小的 Dart web 應用示例開始,并修改
<body>中沒有<script>標簽的部分。HTML and Dart connections 展示了完整的 HTML 代碼。
編輯 HTML 源碼
- 點擊 DartPad 左上角的 HTML。從 Dart 代碼視圖,切換到(不存在的) HTML 代碼視圖。
- 添加下面的 HTML 代碼。
<p id="RipVanWinkle">
RipVanWinkle paragraph.
</p>
- 點擊 HTML OUTPUT 查看瀏覽器如何渲染 HTML。
關于 HTML 源碼
這段 HTML 代碼和在本教程先前各種圖里顯示的 HTML 代碼相似,但它更簡單。在 DartPad 中,你真正需要關心的唯一的標簽——本例中的<p>。你不需要關心包裹著它的標簽,例如<html>和<body>。因為 DartPad 知道你的 Dart 代碼在哪里,你不需要一個<script>標簽。
注意:HTML and Dart connections 展示了在 DartPad 之外運行 web 應用的全部 HTML 代碼。
這個段落標簽有一個“RipVanWinkle”標識符。你在下一步創(chuàng)建的 Dart 代碼會使用這個 ID 來獲取段落元素。
編輯 Dart 源碼
- 點擊 DartPad 左上角的 DART。從 HTML 代碼視圖切換到 Dart 代碼視圖。
- 按如下所示修改 Dart 代碼。
import 'dart:html';
void main() {
querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';
}
- 點擊 Run 來執(zhí)行代碼。
在 HTML OUTPUT 標簽頁中的文本變?yōu)?“Wake up, sleepy head!”
關于 Dart 源碼
讓我們逐句查看這段 Dart 代碼。
導入庫
import指令導入了指定的庫,使這個庫里的所有類和函數在你的程序里可用。
import 'dart:html';
這段程序導入了 Dart 的 HTML 庫,它包含了操作 DOM 的關鍵類和函數。關鍵的類有:
| Dart 類 | 描述 |
|---|---|
| Node | 實現一個 DOM 節(jié)點。 |
| Element | 一個 Node 的子類;實現一個 web 頁面元素。 |
| Document | Node 的另一個子類;實現文檔對象。 |
Dart 核心庫包含另外有用的類:List,一個可以指定它的成員類型的參數化的類。List<Element> 一個 Element 保存它的子 Element 的列表的實例。
使用 querySelector() 函數
應用的main()函數包含一行代碼,它有點像多個事情接連發(fā)生的連寫語句。讓我們拆解它。
querySelector()是一個通過 Dart HTML 庫提供的頂級函數,它從 DOM 獲取元素對象。
querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';
querySelector()的參數——一個字符串,是一個用于標識該對象的 CSS 選擇器。最常見的 CSS 選擇器指定類、標識符、或屬性。當我們之后向迷你應用中添加一個 CSS 文件時,會詳細考慮這些選擇器。在本例中,RipVanWinkle是 HTML 文件中聲明的段落元素的唯一 ID,#RipVanWinkle指定了這個 ID。
querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';
從 DOM 獲取元素的另一個有用的方法是querySelectorAll(),它返回匹配提供的選擇器的所有元素對象的列表。
設置一個元素的文本
在 DOM 中,一個頁面元素的文本包含一個子節(jié)點,具體而言,一個文本節(jié)點。在下圖中,包含字符串 “RipVanWinkle paragraph.” 的節(jié)點是一個文本節(jié)點。

更復雜的文本,例如,帶樣式變化或嵌入鏈接和圖片的文本,表現為一個文本節(jié)點和其它對象的子節(jié)點樹。
在 Dart 中,你可以簡單地使用元素地text屬性,它有一個 getter 為你遍歷本節(jié)點的子節(jié)點樹,并提取它們的文本。
querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';
然而,如果這個文本節(jié)點有樣式(因此,是一個子節(jié)點樹),獲取文本然后立刻設置它,可能會改變 DOM ,這是由于丟失了子節(jié)點樹的信息。通常,和我們的 RipVanWinkle 例子一樣,這種簡化沒有副作用。
賦值操作符(=)設置通過querySelector()函數返回的元素的文本為字符串“Wake up, sleepy head!”。
querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';
這導致瀏覽器立刻重新渲染包含這個應用的網頁,從而在網頁上動態(tài)地顯示文本。
HTML 和 Dart 相關聯
Dart web 應用在運行時動態(tài)地改變在瀏覽器窗口中的文本。當然,只給網頁添加文本并不做其它事情可以直接由 HTML 完成。這個小應用僅僅向你展示了如何連接一個 Dart 應用和一個網頁。
在 DartPad 中,Dart 代碼和 HTML 代碼之間唯一的關聯是這個RipVanWinkleID。

要在 DartPad 之外運行你的應用,你需要編譯 Dart 代碼為 JavaScript。使用 build_runner build 命令編譯你的應用為可部署的 JavaScript。然后,你需要關聯 HTML 和生成的 JavaScript:你必須在 HTML 添加<script>標簽來告訴瀏覽器在哪里找到編譯的 Dart 代碼。
下面是本應用完整的 HTML 代碼,假設 Dart 代碼是在名為main.dart的文件中:
<!DOCTYPE html>
<html>
<head>
<title>A Minimalist App</title>
<script defer src="main.dart.js"></script>
</head>
<body>
<p id="RipVanWinkle">
RipVanWinkle paragraph.
</p>
</body>
</html>
使用 CSS 給應用添加樣式
大多數 HTML 使用級聯樣式表(CSS)來定義樣式控制頁面元素的外觀。讓我們?yōu)檫@個迷你應用自定義 CSS。
- 點擊CSS。從 Dart 代碼視圖切換到(不存在的) CSS 代碼視圖。
- 添加下面的 CSS 代碼:
#RipVanWinkle {
font-size: 20px;
font-family: 'Open Sans', sans-serif;
text-align: center;
margin-top: 20px;
background-color: SlateBlue;
color: Yellow;
}
在 HTML OUTPUT 下面立刻顯示變化來反映新的樣式,這僅應用于 ID 是RipVanWinkle的頁面元素。
關于 CSS 選擇器
CSS 選擇器可以是,關于在 HTML 中建立的元素的ID、CSS 類和其它信息。你的 Dart 代碼可以使用這個信息通過一個 CSS 選擇器來獲取元素——一個用來從 DOM 中選擇匹配元素的模式。CSS 選擇器允許 CSS、HTML 和 Dart 代碼來引用相同的對象。通常,一個選擇器指定一個 ID、一個 HTML 元素類型、一個 CSS 類或一個屬性。選擇器也可以被嵌套。
CSS 選擇器在 Dart 程序中是很重要的,因為你通過querySelector()和querySelectorAll()使用它們從 DOM 中獲取匹配的元素。很多時候,Dart 程序通過querySelector()使用 ID 選擇器,通過querySelectorAll()使用類選擇器。
下面是一些 CSS 選擇器的例子:
| 選擇器類型 | 例子 | 描述 |
|---|---|---|
| ID 選擇器 | #RipVanWinkle | 匹配一個單一的,唯一的元素 |
| HTML 元素 | p | 匹配所有的段落 |
| HTML 元素 | h1 | 匹配所有的 h1 標題 |
| CSS 類 | .classname | 匹配所有使用這個類名的條目 |
| 通配符 | * | 匹配所有元素 |
| 屬性 | input[type=”button”] | 匹配所有 input 元素的按鈕 |
如你所見,迷你應用使用了一個 CSS 選擇器——ID 選擇器
#RipVanWinkle,即使當時還沒有 CSS 文件。你不需要為一個 Dart 程序創(chuàng)建一個 CSS 文件。你也不需要因要使用一個 CSS 選擇器而創(chuàng)建一個 CSS 文件。CSS 選擇器是建立在 HTML 文件中,并通過 Dart 程序用來選擇匹配的元素。
讓我們看看迷你應用的 CSS 代碼。迷你應用的 CSS 文件有一條 CSS 規(guī)則。一個 CSS 規(guī)則有兩個主要部分:一個選擇器和一組聲明。

在迷你應用中,選擇器#RipVanWinkle是一個 ID 選擇器,通過哈希符號 (#)標識;它通過指定的 ID 匹配單獨的、唯一的元素——我們現在要替換的RipVanWinkle paragraph元素。RipVanWinkle是 HTML 文件中的 ID。在 CSS 文件和 Dart 代碼中使用哈希符號(#)引用它。在 HTML 文件中指定類名不需要句點(.),在 CSS 文件和 Dart 代碼中使用一個句點(.)引用它。
在 CSS 規(guī)則的花括號之中的是一系列聲明,每個都以分號(;)結尾。每個聲明指定一個屬性和它的值。這一組聲明合起來為所有匹配的元素定義了樣式表。樣式表用來設置在網頁上匹配元素的外觀。

RipVanWinkle paragraph元素的 CSS 規(guī)則指定了幾個屬性;例如,它設置文本顏色為黃色。
其它資源
- language tour 全面介紹了 Dart 語言。
- Dart Tools 列出了包含 Dart 插件的 IDE 和編輯器。