dart 基礎(chǔ)

http://dart.goodev.org/guides/libraries/library-tour

Numbers

dart:core 庫定義了 num, int, 和 double 類,這些類 定義一些操作數(shù)字的基礎(chǔ)功能。

使用 parse() 函數(shù)可以把字符串 轉(zhuǎn)換為 整數(shù)或者浮點數(shù)。

num 類也定義了一個 parse() 函數(shù),這個函數(shù)會嘗試解析 為整數(shù),如果無法解析為整數(shù),則會解析為浮點數(shù)(double)。

對于整數(shù),可以指定一個 radix 作為基數(shù):

使用 toString() 函數(shù) (由 Object 對象定義)來把整數(shù)或者浮點數(shù) 轉(zhuǎn)換為字符串。使用 num 類的函數(shù) toStringAsFixed() 可以限定 小數(shù)點的位數(shù)。如果要指定轉(zhuǎn)換為字符串的有效位數(shù), 則可以使用定義在 num 類的 函數(shù) toStringAsPrecision()

更多信息,參考 API 文檔中每個類的描述: int, double,num。 另外還有 dart:math提供了關(guān)于數(shù)學(xué)運算的常用功能。

Strings and regular expressions(字符串和正則表達式)

Dart 中的字符串是一個不可變的 UTF-16 碼元(code units)序列。 在語言預(yù)覽中對 字符串有詳細的介紹。 你可以使用正則表達式(RegExp 對象) 來搜索字符串中的內(nèi)容或者 替換部分字符串。

String 類定義了一些函數(shù) split(), contains(), startsWith(), endsWith() 等來處理各種字符串操作。

Searching inside a string(在字符串內(nèi)搜索)

可以在字符串內(nèi)查找特定字符的位置,還可以 判斷字符串是否以特定字符串開始和結(jié)尾。 例如:

Extracting data from a string(從字符串中提取數(shù)據(jù))

可以從字符串中獲取到單個的字符,單個字符可以是 String 也可以是 int 值。 準(zhǔn)確來說,實際得到的是一個 UTF-16 code units; 對于碼率比較大的字符,實際得到的是兩個 code units,例如 treble clef 符號 (‘\u{1D11E}’) 。

還可以從字符串中提取一個子字符串,或者把字符串分割為 多個子字符串:

Converting to uppercase or lowercase(大小寫轉(zhuǎn)換)

字符串大小寫轉(zhuǎn)換是非常 簡單的:

注意: 注意上面的轉(zhuǎn)換方式對于某些語言是有問題的。例如對于土耳其語言 中的無點 I 的轉(zhuǎn)換就是錯誤的。

Trimming and empty strings(裁剪和判斷空字符串)

trim() 函數(shù)可以刪除字符串前后的空白字符。使用 isEmpty 可以 判斷字符串是否為空(長度為 0)。

Replacing part of a string(替換部分字符)

Strings 是不可變的對象,可以創(chuàng)建他們但是無法修改。 如果你仔細研究了 String API 文檔,你會注意到并沒有 函數(shù)可以修改字符串的狀態(tài)。 例如,函數(shù) replaceAll() 返回一個新的 String 對象而不是修改 舊的對象:

Building a string(創(chuàng)建字符串)

使用 StringBuffer 可以在代碼中創(chuàng)建字符串。 只有當(dāng)你調(diào)用 StringBuffer 的 toString() 函數(shù)的時候,才會創(chuàng)建一個 新的 String 對象。而 writeAll() 函數(shù)還有一個可選的參數(shù)來指定每個字符串的分隔符, 例如下面指定空格為分隔符:

Regular expressions(正則表達式)

RegExp 類提供了 JavaScript 正則表達式同樣的功能。 正則表達式可以高效率的搜索和匹配 字符串。

還可以直接操作 RegExp 類。 Match 類提供了 訪問正則表達式匹配到的內(nèi)容。

More information(更多信息)

參考 String API 文檔 來查看 String 類的所有 方法。同時還可以參考下面這些類的 api 文檔: StringBuffer, Pattern, RegExp,Match.

Collections

Dart 提供了一些核心的集合 API,包含 lists, sets, 和 maps。

Lists

在語言預(yù)覽中已經(jīng)介紹過如何 創(chuàng)建 lists了。另外還可以 使用 List 構(gòu)造函數(shù)來創(chuàng)建 List 對象。 List 類來定義了一些函數(shù)可以添加或者刪除里面的數(shù)據(jù)。

使用 indexOf() 來查找 list 中對象的索引:

排序一個 list 可以使用 sort() 函數(shù)。還可以提供一個用來排序 的比較方法。排序方法返回值 為:對于小的值 為 < 0;對于相同的值為 0 ;對于大的值為 > 0。 下面的示例使用由 Comparable 定義的 compareTo() 函數(shù),該函數(shù)也被 String 實現(xiàn)了。

List 是泛型類型,所以可以指定 里面所保存的數(shù)據(jù)類型:

參考 List API 文檔 來查看 list 的 所有函數(shù)。

Sets

Dart 中的 Set 是一個無序集合,里面不能保護重復(fù)的數(shù)據(jù)。 由于是無序的,所以無法通過索引來從 set 中獲取數(shù)據(jù):

使用 contains()containsAll() 來判斷 set 中是否包含 一個或者多個對象:

交際是兩個 set 中都有的數(shù)據(jù)的子集:

詳細信息, 參考 Set API 文檔

Maps

map 通常也被稱之為 字典或者 hash ,也是一個無序的集合,里面 包含一個 key-value 對。map 把 key 和 value 關(guān)聯(lián)起來可以 方便獲取數(shù)據(jù)。和 JavaScript 不同的是, Dart objects 不是 maps。

下面是兩種定義 map 對象的方式:

使用中括號來訪問或者設(shè)置 map 中的數(shù)據(jù), 使用 remove() 函數(shù)來從 map 中刪除 key 和 value。

還可以獲取 map 的所有 key 和 value:

containsKey() 判斷 map 是否包含一個 key。由于 map 的 value 可以為 null, 所有通過 key 來獲取 value 并通過 判斷 value 是否為 null 來判斷 key 是否存在是 行不通的。所以添加了一個判斷 key 是否存在的函數(shù):

map 還有一個 putIfAbsent() 函數(shù)來設(shè)置 key 的值,但是只有該 key 在 map 中不存在的時候才設(shè)置這個值,否則 key 的值保持不變。該函數(shù)需要 一個方法返回 value:

詳細信息請參考 Map API 文檔

Common collection methods(常用的集合函數(shù))

List, Set, 和 Map 上可以使用很多常用的集合函數(shù)。 Iterable 類定義了一些常用的功能, List 和 Set 實現(xiàn)了 Iterable 。

注意: 雖然 Map 沒有實現(xiàn) Iterable,但是 Map 的 keysvalues 屬性實現(xiàn)了 Iterable。

可以使用 isEmpty 函數(shù)來判斷集合是否為空的:

使用 forEach() 函數(shù)可以對集合中的每個數(shù)據(jù)都應(yīng)用 一個方法:

在 Map 上使用 forEach() 的時候,方法需要能 接收兩個參數(shù)(key 和 value):

Iterables 也有一個 map() 函數(shù),這個函數(shù)返回一個包含所有數(shù)據(jù)的對象:

注意: map() 函數(shù)返回的對象也是一個 Iterable,該對象是懶求值(lazily evaluated) 的,只有當(dāng)訪問里面的值的時候, map 的方法才被調(diào)用。

可以使用 map().toList() 或者 map().toSet() 來 強制立刻執(zhí)行 map 的方法:

Iterable 的 where() 函數(shù)可以返回所有滿足特定條件的數(shù)據(jù)。 any() 判斷是否有數(shù)據(jù)滿足特定條件, every() 判斷是否所有數(shù)據(jù)都滿足 特定條件。

更多信息請參考 Iterable API 文檔,以及 List, Set, 和 Map 的文檔。

URIs

Uri 類 提供了 編碼和解碼 URI(URL) 字符的功能。 這些函數(shù)處理 URI 特殊的字符,例如 &=。 Uri 類還可以解析和處理 URI 的每個部分,比如 host, port, scheme 等。

Encoding and decoding fully qualified URIs(編碼解碼URI)

要編碼和解碼除了 URI 中特殊意義(例如 /, :, &, #)的字符, 則可以使用 encodeFull()decodeFull() 函數(shù)。這兩個函數(shù)可以用來編碼和解碼整個 URI,并且保留 URI 特殊意義的字符不變。

注意上面 somemessage 之間的空格被編碼了。

Encoding and decoding URI components(編碼解碼URI組件)

使用 encodeComponent()decodeComponent() 可以編碼 和解碼 URI 中的所有字符,特殊意義的字符(/, &, 和 : 等) 也會編碼,

注意上面特殊字符也被編碼了,比如 / 編碼為 %2F

Parsing URIs

如果有個 Uri 對象或者 URI 字符串,使用 Uri 的屬性 可以獲取每個部分,比如 path。使用 parse() 靜態(tài) 函數(shù)可以從字符串中解析一個 Uri 對象:

Building URIs

使用 Uri() 構(gòu)造函數(shù)可以從 URI 的 各個部分來構(gòu)造一個 Uri 對象:

更多信息參考 Uri API 文檔

Dates and times

DateTime 對象代表某個時刻。時區(qū)是 UTC 或者 本地時區(qū)。

一些構(gòu)造函數(shù)可以創(chuàng)建 DateTime 對象:

millisecondsSinceEpoch 屬性返回自從 “Unix epoch”—January 1, 1970, UTC 以來的毫秒數(shù)值:

使用 Duration 類可以計算兩個日期之間的間隔, 還可以前后位移日期:

警告: 使用 Duration 來在 DateTime 對象上前后移動數(shù)天可能會有問題, 比如像夏令時等時間問題。如果要按照天數(shù)來位移時間,則 需要使用 UTC 日期。

更多詳細信息參考 DateTimeDuration 的 API 文檔。

Utility classes(工具類)

核心庫還包含了一些常用的工具類,比如排序、 值映射以及遍歷數(shù)據(jù)等。

Comparing objects(比較對象)

實現(xiàn) Comparable 接口表明該對象可以相互比較,通常用來 排序。compareTo() 函數(shù)對于 小于的值返回 < 0 ; 相同的值返回 0 ; 大于的值返回 > 0、

Implementing map keys

Dart 中的每個對象都有一個整數(shù) hash 碼,這樣每個對象都 可以當(dāng)做 map 的 key 來用。但是,你可以覆寫 hashCode getter 來自定義 hash 碼的實現(xiàn),如果你這樣做了,你也需要 同時覆寫 == 操作符。相等的對象(使用 == 比較)的 hash 碼應(yīng)該一樣。Hasm 碼并不要求是唯一的, 但是應(yīng)該具有良好的分布形態(tài)。

Iteration

IterableIterator 類支持 for-in 循環(huán)。當(dāng)你創(chuàng)建一個類的時候,繼承或者實現(xiàn) Iterable 可以 提供一個用于 for-in 循環(huán)的 Iterators。 實現(xiàn) Iterator 來定義實際的遍歷操作。

Exceptions

Dart 核心庫定義了很多常見的異常和錯誤類。 異常通常是一些可以預(yù)知和預(yù)防的例外情況。 錯誤這是無法預(yù)料的并且不需要預(yù)防的情況。

下面是一些常見的錯誤:

<dl style="font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; box-sizing: border-box; margin-top: 0px; margin-bottom: 22px; caret-color: rgb(17, 17, 17); color: rgb(17, 17, 17); font-family: "Source Sans Pro", sans-serif;">

<dt style="box-sizing: border-box; line-height: 1.42857143; font-weight: bold;">NoSuchMethodError</dt>

<dd style="box-sizing: border-box; line-height: 1.42857143; margin-left: 0px; margin-bottom: 15px;">

當(dāng)在一個對象上調(diào)用一個該對象沒有 實現(xiàn)的函數(shù)會拋出該錯誤。

</dd>

<dt style="box-sizing: border-box; line-height: 1.42857143; font-weight: bold;">ArgumentError</dt>

<dd style="box-sizing: border-box; line-height: 1.42857143; margin-left: 0px; margin-bottom: 15px;">

調(diào)用函數(shù)的參數(shù)不合法會拋出這個錯誤。

</dd>

</dl>

拋出一個應(yīng)用相關(guān)的異常是一種用來表明有錯誤發(fā)生的常見 方法。你還可以通過實現(xiàn) Exception 接口來自定義 一些異常。

更多信息,請參考 ExceptionsException API 文檔

dart:async - asynchronous programming

異步編程通常使用回調(diào)函數(shù),但是 Dart 提供了另外的 選擇: FutureStream 對象。 Future 和 JavaScript 中的 Promise 類似,代表在將來某個時刻會返回一個 結(jié)果。Stream 是一種用來獲取一些列數(shù)據(jù)的方式,例如 事件流。 Future, Stream, 以及其他異步操作的類在 dart:async 庫中。

注意: 你并不是都需要直接使用 Future 和 Stream。 Dart 語言有一些異步功能的關(guān)鍵字,例如 asyncawait。 詳細信息 請參考 異步支持

dart:async 庫在 web app 和命令行 app 都可以使用。 只需要導(dǎo)入 dart:async 即可使用:

Future

在 Dart 庫中隨處可見 Future 對象,通常異步函數(shù)返回的對象就是一個 Future。 當(dāng)一個 future 執(zhí)行完后,他里面的值 就可以使用了。

Using await

在直接使用 Future api 之前,你可以考慮先使用 await。 使用 await 的表達式比直接使用 Future api 的代碼要更加 容易理解。

例如下面的方法。使用 Future 的 then() 函數(shù)來 執(zhí)行三個異步方法, 每個方法執(zhí)行完后才繼續(xù)執(zhí)行后一個方法。

下面是使用 await 表達式實現(xiàn)的同樣功能的代碼, 看起來更像是同步代碼,更加容易理解:

異步方法可以把 Future 中的錯誤當(dāng)做 異常來處理。 例如:

重要: 異步方法(帶有關(guān)鍵字 async 的方法)會返回 Future。 如果你不想讓你的方法返回 future,則 不要使用 async 關(guān)鍵字。 例如,你可以在你的方法里面調(diào)用一個 異步方法。

關(guān)于使用 await 和相關(guān) Dart 語言的其他特性,請參考 異步支持

Basic usage

可以使用 then() 來在 future 完成的時候執(zhí)行其他代碼。例如 HttpRequest.getString() 返回一個Future,由于 HTTP 請求是一個 耗時操作。使用 then() 可以在 Future 完成的時候執(zhí)行其他代碼 來解析返回的數(shù)據(jù):

使用 catchError() 來處理 Future 對象可能拋出的 各種異常和錯誤:

then().catchError() 模式就是異步版本的 try-catch

重要: 確保是在 then() 返回的 Future 上調(diào)用 catchError(), 而不是在 原來的 Future 對象上調(diào)用。否則的話,catchError() 就只能處理原來 Future 對象拋出的異常而無法處理 then() 代碼 里面的異常。

Chaining multiple asynchronous methods

then() 函數(shù)返回值為 Future,可以把多個異步調(diào)用給串聯(lián)起來。 如果 then() 函數(shù)注冊的回調(diào)函數(shù)也返回一個 Future,而 then()返回一個同樣的 Future。如果回調(diào)函數(shù)返回的是一個其他類型的值, 則 then() 會創(chuàng)建一個新的 Future 對象 并完成這個 future。

上面的示例中,代碼是按照如下順序執(zhí)行的:

  1. costlyQuery()
  2. expensiveWork()
  3. lengthyComputation()

Waiting for multiple futures

有時候,你的算法要求調(diào)用很多異步方法,并且等待 所有方法完成后再繼續(xù)執(zhí)行。使用 Future.wait() 這個靜態(tài)函數(shù)來管理多個 Future 并等待所有 Future 執(zhí)行完成。

Stream

Stream 在 Dart API 中也經(jīng)常出現(xiàn),代表一些列數(shù)據(jù)。 例如, HTML 按鈕點擊事件就可以使用 stream 來表示。 還可以把讀取文件內(nèi)容當(dāng)做一個 Stream。

Using an asynchronous for loop

有時候可以使用異步 for 循環(huán)(await for)來 替代 Stream API。

例如下面的示例中,使用 Stream 的 listen() 函數(shù)來訂閱 一些文件,然后使用一個方法參數(shù)來 搜索每個文件和目錄。

下面是使用 await 表達式和異步 for 循環(huán) 實現(xiàn)的等價的代碼, 看起來更像是同步代碼:

重要: 在使用 await for 之前請確保使用之后的代碼看起來確實是 更加清晰易懂了。例如,對于 DOM時間監(jiān)聽器通常 不會使用 await for,原因在于 DOM 發(fā)送 無盡的事件流。 如果使用 await for 來在同一行注冊兩個 DOM 事件監(jiān)聽器, 則第二個事件在不會被處理。

關(guān)于使用 await 和相關(guān) Dart 語言的其他特性, 請參考 異步支持

Listening for stream data

要想在每個數(shù)據(jù)到達的時候就去處理,則可以選擇使用 await for 或者 使用 listen() 函數(shù)來訂閱事件:

上面的示例中, onClick 屬性是 “submitInfo” 按鈕提供的一個 Stream 對象。

如果你只關(guān)心里面其中一個事件,則可以使用這些屬性: first, last, 或者 single。要想在處理事件之前先測試是否滿足條件,則 使用 firstWhere(), lastWhere(), 或者 singleWhere() 函數(shù)。

如果你關(guān)心一部分事件,則可以使用 skip(), skipWhile(), take(), takeWhile(), 和 where() 這些函數(shù)。

Transforming stream data

經(jīng)常你需要先轉(zhuǎn)換 stream 里面的數(shù)據(jù)才能使用。 使用 transform() 函數(shù)可以生產(chǎn)另外一個數(shù)據(jù)類型 的 Stream 對象:

上面的代碼使用兩種轉(zhuǎn)換器(transformer)。第一個使用 UTF8.decoder 來把整數(shù)類型的數(shù)據(jù)流轉(zhuǎn)換為字符串類型的數(shù)據(jù)流。然后使用 LineSplitter 把字符串類型數(shù)據(jù)流轉(zhuǎn)換為按行分割的數(shù)據(jù)流。 這些轉(zhuǎn)換器都來至于 dart:convert 庫。 參考 dart:convert ) 了解詳情。

Handling errors and completion

使用異步 for 循環(huán) (await for) 和使用 Stream API 的 異常處理情況是有 區(qū)別的。

如果是異步 for 循環(huán),則可以 使用 try-catch 來處理異常。

在 stream 關(guān)閉后執(zhí)行的代碼位于異步 for 循環(huán) 之后。

如果你使用 Stream API,則需要 使用 onError 函數(shù)來處理異常。 stream 完成后執(zhí)行的代碼要通過 onDone 函數(shù) 來執(zhí)行。

More information

關(guān)于在命令行應(yīng)用中使用 Future 和 Stream 的更多示例,請參考 dart:io 里面的內(nèi)容。 下面也是一些可以參考的文章和教程:

dart:math - math and random

Math 庫提供了常見的數(shù)學(xué)運算功能,例如 sine 和 cosine, 最大值、最小值等,還有各種常量 例如 pie 等。Math 庫中 的大部分函數(shù)都是頂級方法。

導(dǎo)入 dart:math 就可以使用 Math 庫了。 下面的示例代碼使用前綴 math 來引用庫中的頂級 方法和常量:

Trigonometry

Math 庫中提供了常見的三角運算功能:

注意: 上面這些函數(shù)是基于弧度的不是基于角度的。

Maximum and minimum

Math 庫提供了 max()min() 函數(shù)用來計算最大值和最小值:

Math constants

Math 庫中提供各種數(shù)學(xué)常量,例如 pi, e 等。

Random numbers

使用 Random 類可以生成隨機數(shù)。 在 Random 構(gòu)造函數(shù)中還可以提供一個隨機種子:

也可以生成隨機的布爾值:

More information

詳細的信息可以參考 Math API 文檔 來了解。 還可以參考下面這些類的 API 文檔 num, int,double。

dart:html - browser-based apps

如果要和瀏覽器打交道則需要使用 dart:html 庫, 訪問 DOM 元素和使用 HTML5 API。 DOM 是 Document Object Model 的縮寫,用來 描述 HTML 頁面的結(jié)構(gòu)。

dart:html 還可以用來操作樣式表(CSS)、用 HTTP 請求 來獲取數(shù)據(jù),使用 WebSockets 來獲取數(shù)據(jù)。 HTML5 (和 dart:html) 具有很多其他的 API 在這里并沒有介紹。 只有 Web 應(yīng)用可以使用 dart:html,命令行應(yīng)用無法使用該庫。

注意: 關(guān)于構(gòu)建 Web 應(yīng)用的更高層級的框架,請參考 Polymer DartAngular 2 for Dart

在 web 應(yīng)用中導(dǎo)入 dart:html 就可以使用 HTML 相關(guān)的功能了:

Manipulating the DOM

要使用 DOM 你需要了解 windows, documents, elements, 和 nodes 等概念。

一個 Window 對象代表 瀏覽器實際的窗口。每個窗口都有一個文檔(Document)對象, 文檔對象是當(dāng)前正在加載的界面。Window 對象還可以訪問各種 API,例如 用于存儲數(shù)據(jù)的 IndexedDB、用于動畫的 requestAnimationFrame 等。 在多窗口瀏覽器中,每個窗口(tab 也)都有 自己的 Window 對象。

使用 Document 對象, 可以創(chuàng)建和操縱 document 中的 Elements 對象。 注意 Document 本身也是一個 element,也是可以 被修改的。

DOM 模型是很多 Nodes 組成的樹狀結(jié)構(gòu)。這些 nodes 通常 是 elements,但是也可以是 attributes、 text、 comments、 和其他 DOM 類型。 除了跟節(jié)點沒有父節(jié)點以外,其他 DOM 中的節(jié)點都有一個 父節(jié)點,還有可能帶有很多子節(jié)點。

Finding elements

在操作一個 element 之前,你需要先找到這個 element。 使用查詢語法可以查找所需要的 element。

使用頂級方法 querySelector()querySelectorAll() 可以查找一個或者多個符合條件的 element。可以根據(jù) ID、class、tag、name 或者 這些的組合來查詢 element。 CSS 選擇器 規(guī)范 定義了選擇器的形式, 例如使用 # 前綴代表 ID,英文句號 (.) 代表 classes。

使用 querySelector() 方法可以獲取第一個符合選擇器要求的元素; 而 querySelectorAll() 返回所有符合 選擇器要求的元素結(jié)合。

Manipulating elements

可以使用屬性(properties)來修改 element 的狀態(tài)。 Node 和子類型 Element 定義了所有 element 都具有的屬性。例如, 所有 element 都有 classes, hidden, id, style, 和 title 屬性,你可以使用這些屬性來修改 element 的狀態(tài)。 Element 的 子類還定義了其他屬性,比如 AnchorElement 定義了 href 屬性。

例如下面的示例在 HTML 中設(shè)置一個錨鏈接:

<a> 標(biāo)簽使用 href 定義了一個 element 和一個包含文字 “l(fā)inktext” 的 text node(使用 text 屬性訪問)。使用 AnchorElement 的 href 屬性 可以修改點擊該鏈接跳轉(zhuǎn)的地址:

通常你需要在多個 element 上設(shè)置屬性。例如,下面的示例在 所有 class 樣式帶有 “mac”, “win”, 或者 “l(fā)inux” 的 element 上設(shè)置hidden 屬性。設(shè)置 hidden 屬性為 true 和 設(shè)置 CSS 樣式 display:none 是同樣的效果。

當(dāng)屬性不能訪問或者不方便訪問的時候,可以使用 Element 的 attributes 屬性。 這個屬性是一個 Map<String, String>,里面的 key 為屬性名字。所有 HTML 元素的 屬性名字以及意義,請參考 MDN Attributes 網(wǎng)頁。下面是一個設(shè)置 屬性值的示例:

Creating elements

還可以創(chuàng)建新的 element 然后添加到 HTML 頁面的 DOM 中。下面的示例創(chuàng)建了一個 段落 (<p>) 元素:

使用 HTML 文本也可以創(chuàng)建 element。所包含的子元素 也一起被創(chuàng)建:

注意上面的 elem2 對象是一個 ParagraphElement 。

給新創(chuàng)建的 Element 指定一個父節(jié)點可以把這個 Element 添加到 DOM 中。 可以把 Element 添加到任何已經(jīng)存在于 DOM 中的其他 Element 的 children 中。 例如,下面的示例,body 是一個 element,使用 children 屬性來 訪問該元素的所有子元素(返回的是一個 List<Element>),然后把新的 elem2 添加 到子元素集合中。

Adding, replacing, and removing nodes

之前說過,element 也是 node 的一種。使用 Node 的 nodes 屬性可以 獲取到當(dāng)前 node 的所有子元素,nodes 返回的是 List<Node> ( children 屬性只包含 Element 類型的 nodes)。 獲取到這個 Node list 后,就可以使用 List 的各種函數(shù)來 處理這些 Node 對象了。

使用 List 的add() 函數(shù)可以把一個 node 添加到所有子元素的 最后:

使用 Node 的 replaceWith() 函數(shù)可以替換一個 Node:

使用 Node 的 remove() 函數(shù)來刪除 node:

Manipulating CSS styles

CSS(cascading style sheets 的縮寫)定義了 DOM 元素的 UI 樣式。 在一個 element 上附加 ID 和 class 屬性可以修改 其應(yīng)用的 CSS 樣式。

沒有 element 都有一個 classes 屬性(field),該屬性的類型為 List。 添加和移除上面的 CSS 類就是向這個集合中添加和刪除字符串。 流入,下面的示例中給 element 添加了 warning CSS 類樣式。

通過 ID 來查找元素非常高效。通過 id 屬性你可以動態(tài)給一個 Element 指定 一個 ID 值。

使用級聯(lián)調(diào)用可以減少 需要編寫的代碼:

使用 ID 和 CSS 的 classes 來應(yīng)用樣式是最佳的方式,但是有時候 你還是希望直接在 element 上應(yīng)用具體的樣式,則 可以直接使用 style 屬性:

Handling events

要響應(yīng)像點擊、聚焦等外部事件,你需要使用事件監(jiān)聽器。 在頁面上的任何 element 上都可以注冊事件監(jiān)聽器。 事件分發(fā)和傳遞是一個很復(fù)雜的議題: 如果你是 Web 開發(fā)新手, 請到 這里來 詳細研究這個事件分發(fā)機制

使用 *element*.on*Event*.listen(*function*)來添加事件監(jiān)聽器, 這里的 *Event* 是事件的名字,而 *function* 是事件處理器。

例如,下面是處理按鈕點擊的事件:

事件可以通過 DOM 樹來向上或者向下傳遞。 通過 e.target 可以獲取是那個 element 觸發(fā)該事件的:

要查看所有可以注冊的事件名字,可以查看 Element 文檔中的 “onEventType” 屬性。 下面是一些常見的事件:

  • change

  • blur

  • keyDown

  • keyUp

  • mouseDown

  • mouseUp

Using HTTP resources with HttpRequest

HttpRequest 類是之前 大家耳熟能詳?shù)?XMLHttpRequest 的功能一樣,使用該類 可以在 web 應(yīng)用總訪問 HTTP 資源。 一般而言, AJAX 風(fēng)格的應(yīng)用會很依賴 HttpRequest。使用 HttpRequest 來 動態(tài)的加載 JSON 數(shù)據(jù)或者其他資源。 還可以動態(tài)的向服務(wù)器發(fā)送數(shù)據(jù)。

下面的示例假設(shè)所有的資源都是來至于和當(dāng)前腳本文件位于 同一個 web 服務(wù)器。由于瀏覽器的安全限制, HttpRequest 要使用 其他服務(wù)器的資源是比較麻煩的。如果你需要訪問 其他服務(wù)器上的資源, 你需要使用 JSONP 技術(shù)或者 啟用另外一個資源服務(wù)器的 CORS header。

Getting data from the server

HttpRequest 的靜態(tài)函數(shù) getString() 可以很方便的從服務(wù)器獲取資源。 使用 await 來確保 getString() 調(diào)用資源返回后再 在繼續(xù)執(zhí)行后面的代碼:

dart:convert 中會介紹 JSON API 相關(guān)的內(nèi)容。

使用 try-catch 來指定異常處理代碼:

如果除了返回的文本數(shù)據(jù)以外你還需要 訪問 HttpRequest,你可以使用 request() 靜態(tài)函數(shù)。下面 是一個讀取 XML 數(shù)據(jù)的示例:

可以使用 full API 來處理各種情況。例如, 設(shè)置請求 header 信息。

下面是使用 HttpRequest full API 的常用流程:

  1. 創(chuàng)建 HttpRequest 對象。
  2. 使用 GET 或者 POST 打開一個 URL。
  3. 添加事件處理器。
  4. 發(fā)送請求。

例如:

Sending data to the server

HttpRequest 還可以使用 HTTP POST 函數(shù)來向服務(wù)器發(fā)送數(shù)據(jù)。 例如,你可能希望動態(tài)的提交數(shù)據(jù)到服務(wù)器。 向 RESTful web 服務(wù)器發(fā)送 JSON 數(shù)據(jù)是一種非常常見的情況。

在表單處理中提交數(shù)據(jù)需要提供一個 name-value 數(shù)據(jù)對,該數(shù)據(jù)還需要 使用 URI 編碼(關(guān)于 URI 類的信息請 參考 URIs 文檔)。 如果要在表單處理器中提交數(shù)據(jù)則還 需要設(shè)置 Content-type header 為 application/x-www-form-urlencode

Sending and receiving real-time data with WebSockets

WebSocket 可以讓你的 web 應(yīng)用和服務(wù)器持續(xù)的交互數(shù)據(jù),不用 一直的輪詢。創(chuàng)建 WebSocket 的服務(wù)器會監(jiān)聽 ws:// 開頭的 URL, 例如 ws://127.0.0.1:1337/ws。 通過 WebSocket 發(fā)送的數(shù)據(jù)可以是字符串或者 blob。 通常都是使用 JSON 格式的字符串。

要在 web 應(yīng)用中使用 WebSocket,需要先創(chuàng)建 WebSocket 對象,把 WebSocket URL 作為該對象的參數(shù)。

Sending data

使用 send() 函數(shù)向 WebSocket 發(fā)送數(shù)據(jù):

Receiving data

要從 WebSocket 接收數(shù)據(jù),需要注冊一個事件 監(jiān)聽器:

消息事件處理函數(shù)的參數(shù)為 MessageEvent 對象。 該對象的 data 變量保存了服務(wù)器返回的數(shù)據(jù)。

Handling WebSocket events

你的應(yīng)用可以處理如下的 WebSocket 事件:open, close, error, 和 (前面演示的) message。下面是演示各種事件 的 示例:

More information

上面只是簡單的介紹了 dart:html 庫。更多信息 請參考 dart:html。 Dart 還有一些 web 特殊領(lǐng)域的 api,例如 web audio, IndexedDB, 和 WebGL

dart:io - I/O for command-line apps

dart:io 庫 提供了一些和 文件、目錄、進程、sockets、 WebSockets、和 HTTP 客戶端以及服務(wù)器的 API。 只有命令行應(yīng)用可以使用 dart:io 庫,web app 無法使用。

一般而言,dart:io 庫實現(xiàn)和提供的是異步 API。 同步函數(shù)很容易阻塞應(yīng)用,后期擴展起來非常麻煩。 因此,大部分的操作返回值都是 Future 或者 Stream 對象, 如果你熟悉 Node.js 則對這種 模式會有所了解。

dart:io 里面也有一小部分同步方法,這些方法都使用 sync 前綴命名方法名字。 這里就不再介紹這些同步方法了。

注意: 只有命令行應(yīng)用才能導(dǎo)入 dart:io

Files and directories

I/O 庫可以讓命令行應(yīng)用讀寫文件和查看目錄。 讀取文件有兩種方式:一次讀完或者通過流的方式來讀取。 一次讀完需要把文件內(nèi)容讀到內(nèi)存中,如果文件 非常大或者你希望一邊讀文件一邊處理,則應(yīng)該 使用 Stream, 在 流式讀取文件中介紹。

Reading a file as text

對于編碼為 UTF-8 的文本,可以使用函數(shù) readAsString() 一次性 的讀取整個文本。如果單行文字比較重要,則可以 使用 readAsLines() 來讀取。 這兩個函數(shù)返回一個 Future 對象,當(dāng)文件 讀取完的時候,可以從 Future 對象獲取一個或者多個字符串。

Reading a file as binary

下面的示例把文件數(shù)據(jù)讀取為字節(jié)流。 同樣 readAsBytes() 函數(shù)返回值為 Future, 當(dāng)讀完文件后,可以從 Future 中獲取數(shù)據(jù)。

Handling errors

在 Future 上注冊一個 catchError 來處理異常, 還可以在 async 方法中使用 try-catch 來 處理異常:

Streaming file contents

使用 Stream 讀取文件的時候, 使用 Stream API 或者 await for 可以一點點的讀取, 詳情參考 異步支持

Writing file contents

使用 IOSink 可以往文件 寫入內(nèi)容。使用 File 的 openWrite() 函數(shù)獲取到一個 IOSink。 默認的寫模式為 FileMode.WRITE,新寫入的數(shù)據(jù)會完全覆蓋 文件之前的內(nèi)容。

如果想在文件末尾追加內(nèi)容,則可以使用 mode 可選參數(shù),參數(shù)取值 為 FileMode.APPEND

使用 add(List<int> data) 函數(shù)可以寫二進制數(shù)據(jù)到文件。

Listing files in a directory

查找目錄中的所有文件和子目錄是一個異步操作。 list() 函數(shù)返回一個 Stream,當(dāng)遇到文件或者子目錄的時候, Stream 就發(fā)射一個對象。

Other common functionality

File 和 Directory 類包含其他的一些文件操作, 下面只是一些常見的函數(shù):

  • 創(chuàng)建文件或者目錄: create() in File and Directory

  • 刪除文件或者目錄: delete() in File and Directory

  • 獲取文件的長度: length() in File

  • 隨機位置訪問文件: open() in File

參考 FileDirectory 的 API 文檔來 查看所有的函數(shù)。

HTTP clients and servers

dart:io 庫提供了一些命令行應(yīng)用可以用來訪問 HTTP 資源 和運行 HTTP 服務(wù)器的類。

HTTP server

HttpServer 類 提供了用來建構(gòu) Web 服務(wù)器的底層方法。可以匹配 請求處理、設(shè)置 header、處理數(shù)據(jù)等。

下面的示例項目只能返回簡單的文本信息。 服務(wù)器監(jiān)聽本機地址 127.0.0.1 的 8888 端口, 響應(yīng)來自于 /languages/dart 路徑的請求。所有其他的 請求都有默認的請求處理器處理(返回 404 頁面沒發(fā)現(xiàn)的錯誤提示)。

HTTP client

HttpClient 類可以 在命令行應(yīng)用程序或者服務(wù)器應(yīng)用程序中使用,用來請求 HTTP 資源。 可以設(shè)置請求頭、HTTP 請求方式和讀寫 數(shù)據(jù)。HttpClient 無法在 web 應(yīng)用中使用。 在 web 應(yīng)用中可以使用 HttpRequest class。 下面是使用 HttpClient 的一個示例:

More information

除了上面提到的幾個功能外,dart:io 庫還包含 processes, sockets,web sockets 等相關(guān)的 API。

dart:convert - decoding and encoding JSON, UTF-8, and more

dart:convert 庫 里面有一些用來轉(zhuǎn)換 JSON 和 UTF-8 的轉(zhuǎn)換器,還可以自定義 新的轉(zhuǎn)換器。 JSON 是非常流行的數(shù)據(jù)格式。 UTF-8 是一種非常流行的編碼格式, 能夠代表所有 Unicode 字符 集。

命令行應(yīng)用和 web 應(yīng)用都可以使用 dart:convert 庫。 導(dǎo)入 dart:convert 就可以使用該庫了。

Decoding and encoding JSON

使用 JSON.decode() 函數(shù)把 JSON 字符串解碼為 Dart 對象:

使用 JSON.encode() 可以把 Dart 對象 編碼為 JSON 字符串:

默認只支持 int、double、String、bool、null、List或者 Map(key 需要為 string) 這些類型轉(zhuǎn)換為 JSON。 集合對象會使用遞歸的形式來轉(zhuǎn)換每個對象。

對于默認不支持的對象,可以有兩種選擇: 一,調(diào)用 encode() 并指定第二個參數(shù), 該參數(shù)是一個函數(shù)用來返回一個默認支持的對象; 二,不指定第二個參數(shù),則會 調(diào)用該對象的 toJson() 函數(shù)。

Decoding and encoding UTF-8 characters

使用 UTF8.decode() 來解碼 UTF8-encoded 字節(jié)流為 Dart 字符串:

如果是 stream 字節(jié)流則可以在 Stream 的 transform() 函數(shù)上指定 UTF8.decoder

使用 UTF8.encode() 把字符串編碼為 UTF8 字節(jié) 流:

Other functionality

dart:convert 來包含轉(zhuǎn)換 ASCII 和 ISO-8859-1(Latin1) 的轉(zhuǎn)換器。詳情請參考 dart:convert 庫的 API 文檔。

dart:mirrors - reflection

dart:mirrors 庫提供了基本的反射支持。 使用 mirror 來查詢程序的結(jié)構(gòu),也可以 在運行時動態(tài)的調(diào)用方法或者函數(shù)。

dart:mirrors 庫在命令行和 web 應(yīng)用中均可使用。 導(dǎo)入 dart:mirrors 即可開始使用。

警告: 使用 dart:mirrors 可能會導(dǎo)致 dart2js 生成的 JavaScript 代碼 文件非常大!

目前的解決方式是在導(dǎo)入 dart:mirrors 之前添加一個 @MirrorsUsed 注解。 詳情請參考 MirrorsUsed API 文檔。由于 dart:mirrors 庫依然還在 開發(fā)中,所以這個解決方案以后很有可能發(fā)生變化。

Symbols

mirror 系統(tǒng)使用 Symbol 類對象 來表達定義的 Dart 標(biāo)識符名字。 Symbols 在混淆后的代碼也可以 使用。

如果在寫代碼的時候,已經(jīng)知道 symbol 的名字了,則可以使用 #符號名字 的方式直接使用。 直接使用的 symbol 對象是編譯時常量,多次定義引用的是同一個對象。 如果名字不知道,則可以通過 Symbol 構(gòu)造函數(shù)來 創(chuàng)建:

在混淆代碼的時候,編譯器可能使用更加簡短的名字來替代原來的符號(symbol)名字。 要獲取原來的 symbol 名字,使用MirrorSystem.getName() 函數(shù)。該函數(shù) 在代碼混淆的情況下,也能返回正確的 symbol 名字。

Introspection

使用 mirror 功能來檢查程序的結(jié)構(gòu)。可以檢查 類、庫以及對象等。

下面的示例使用 Person 類:

在開始使用之前,需要在一個類或者對象上調(diào)用 reflect 函數(shù)來獲取 到 mirror

Class mirrors

在任何 Type 上面調(diào)用 reflect 函數(shù)來獲取 ClassMirror :

也可以在實例上調(diào)用 runtimeType 獲取該對象的 Type。

獲取到 ClassMirror 后,就可以查詢類的構(gòu)造函數(shù)、成員變量、等信息。 下面是列出類的所有構(gòu)造函數(shù)的示例:

下面是列出類的成員變量的示例:

詳情請參考 ClassMirror 的 API 文檔

Instance mirrors

在對象上調(diào)用 reflect 函數(shù)可以獲取到一個 InstanceMirror 對象。

如果你已經(jīng)有個 InstanceMirror 對象了,但是想知道該對象反射的目標(biāo)對象,則需要 調(diào)用 reflectee

Invocation

獲取到 InstanceMirror 后,就可以調(diào)用里面的函數(shù)、getter和setter了。 詳細信息請參考 API docs for InstanceMirror 的 API 文檔

Invoke methods

使用 InstanceMirror 的 invoke() 函數(shù)來調(diào)用對象的函數(shù)。 第一個參數(shù)為要調(diào)用的函數(shù)名字,第二個參數(shù)為該函數(shù)的 一個位置參數(shù)列表。第三個參數(shù)為可選參數(shù),用來指定命名 參數(shù)。

Invoke getters and setters

使用 InstanceMirror 的 getField()setField() 函數(shù)來 查詢和設(shè)置對象的屬性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,315評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,699評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,882評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,189評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,388評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,613評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,112評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,334評論 2 377

推薦閱讀更多精彩內(nèi)容