Dart 程式設計 - 快速指南



Dart 程式設計 - 概述

Dart 是一種面向物件的語言,使用 C 風格的語法,可以選擇性地編譯成 JavaScript。它支援各種程式設計輔助工具,例如介面、類、集合、泛型和可選型別。

Dart 可以廣泛用於建立單頁應用程式。單頁應用程式僅適用於網站和 Web 應用程式。單頁應用程式允許在網站的不同螢幕之間導航,而無需在瀏覽器中載入不同的網頁。一個經典的例子是 **Gmail** - 當您在收件箱中點選一條訊息時,瀏覽器會停留在同一網頁上,但 JavaScript 程式碼會隱藏收件箱並在螢幕上顯示郵件正文。

Google 釋出了 **Chromium** 的一個特殊版本 - **Dart VM**。使用 Dartium 意味著您不必將程式碼編譯成 JavaScript,直到您準備好測試其他瀏覽器。

下表比較了 Dart 和 JavaScript 的功能。

特性 Dart JavaScript
型別系統 可選的,動態的 弱型別,動態的
是,單繼承 原型繼承
介面 是,多介面
併發 是,使用隔離區 是,使用 HTML5 Web Workers

本教程提供了對 Dart 程式語言的基本理解。

Dart 程式設計 - 環境搭建

本章討論在 Windows 平臺上為 Dart 設定執行環境。

使用 DartPad 線上執行指令碼

您可以使用線上編輯器 https://dartpad.dev/ 線上測試您的指令碼。Dart 編輯器會執行指令碼並顯示 HTML 和控制檯輸出。線上編輯器附帶了一組預設程式碼示例。

下面給出了 **Dartpad** 編輯器的螢幕截圖 -

Dartpad

Dartpad 還允許以更嚴格的方式進行編碼。這可以透過檢查編輯器右下角的“強模式”選項來實現。強模式有助於 -

  • 更強大的靜態和動態檢查
  • 生成更具特色的 JavaScript 程式碼以實現更好的互操作性。

您可以使用 Dartpad 嘗試以下示例

void main() { 
   print('hello world'); 
}

程式碼將顯示以下輸出

hello world

設定本地環境

在本節中,讓我們看看如何設定本地環境。

使用文字編輯器

一些編輯器的示例包括 Windows 記事本、Notepad++、Emacs、vim 或 vi 等。編輯器可能因作業系統而異。原始檔通常以“.dart”副檔名命名。

安裝 Dart SDK

Dart 的當前穩定版本為 **1.21.0**。**dart sdk** 可以從以下地址下載 -

下面給出了 Dart SDK 安裝的螢幕截圖 -

Dart Installation

完成 SDK 安裝後,將 PATH 環境變數設定為 -

<dart-sdk-path>\bin 

驗證安裝

要驗證 Dart 是否已成功安裝,請開啟命令提示符並輸入以下命令 -

Dart 

如果安裝成功,它將顯示 dart 執行時。

IDE 支援

許多 IDE 支援 Dart 指令碼編寫。例如 Jet brains 的 **Eclipse、IntelliJ** 和 **WebStorm**。

以下是使用 **WebStrom IDE** 配置 Dart 環境的步驟。

安裝 WebStorm

WebStorm 的安裝檔案可以從 https://www.jetbrains.com/webstorm/download/#section=windows-version 下載。

WebStorm 安裝檔案適用於 Mac OS、Windows 和 Linux。

下載安裝檔案後,請按照以下步驟操作 -

  • 安裝 Dart SDK:請參考上面列出的步驟

  • 建立一個新的 Dart 專案並配置 Dart 支援

  • 要建立一個新的 Dart 專案,

    • 從歡迎螢幕點選 **建立新專案**

    • 在下一個對話方塊中,點選 **Dart**

  • 如果沒有為 **Dart SDK** 路徑指定值,則提供 SDK 路徑。例如,SDK 路徑可能是 **<dart 安裝目錄>/dart/dartsdk**。

向專案新增 Dart 檔案

要向專案新增 Dart 檔案 -

  • 右鍵點選專案
  • 新建 → Dart 檔案
  • 輸入 Dart 指令碼的名稱

下面給出了 WebStorm 編輯器的螢幕截圖 -

Dart File

dart2js 工具

**dart2js** 工具將 Dart 程式碼編譯成 JavaScript。將 Dart 程式碼編譯成 JS 可以在不支援 Dart VM 的瀏覽器上執行 Dart 指令碼。

dart2js 工具作為 Dart SDK 的一部分提供,可以在 ** /dartsdk/bin 資料夾** 中找到。

要將 Dart 編譯成 JavaScript,請在終端中鍵入以下命令

dart2js - - out = <output_file>.js  <dart_script>.dart

此命令生成一個包含 Dart 程式碼的 JavaScript 等效檔案。有關使用此實用程式的完整教程,請參閱 Dart 官方網站。

Dart 程式設計 - 語法

語法定義了一組編寫程式的規則。每種語言規範都定義了自己的語法。Dart 程式由以下部分組成 -

  • 變數和運算子
  • 函式
  • 表示式和程式設計結構
  • 決策制定和迴圈結構
  • 註釋
  • 庫和包
  • 型別定義
  • 表示為集合/泛型的的資料結構

你的第一個 Dart 程式碼

讓我們從傳統的“Hello World”示例開始 -

main() { 
   print("Hello World!"); 
}

**main()** 函式是 Dart 中的預定義方法。此方法充當應用程式的入口點。Dart 指令碼需要 **main()** 方法才能執行。**print()** 是一個預定義函式,它將指定的字串或值列印到標準輸出,即終端。

以上程式碼的輸出將是 -

Hello World!

執行 Dart 程式

您可以透過兩種方式執行 Dart 程式 -

  • 透過終端
  • 透過 WebStorm IDE

透過終端

要透過終端執行 Dart 程式 -

  • 導航到當前專案的路徑
  • 在終端視窗中鍵入以下命令
dart file_name.dart

透過 WebStorm IDE

要透過 WebStorm IDE 執行 Dart 程式 -

  • 右鍵點選 IDE 上的 Dart 指令碼檔案。(檔案應包含 **main()** 函式以啟用執行)

  • 點選 **“執行 <file_name>”** 選項。下面給出了相同的螢幕截圖 -

Run Test1 Dart

或者,可以點選 Run Button 按鈕或使用快捷鍵 **Ctrl+Shift+F10** 執行 Dart 指令碼。

Dart 命令列選項

Dart 命令列選項用於修改 Dart 指令碼執行。Dart 的常見命令列選項包括以下內容 -

序號 命令列選項 & 描述
1 -c 或 --c

啟用斷言和型別檢查(檢查模式)。

2 --version

顯示 VM 版本資訊。

3 --packages <path>

指定包解析配置檔案的路徑。

4 -p <path>

指定在何處查詢匯入的庫。此選項不能與 --packages 一起使用。

5 -h 或 --help

顯示幫助。

啟用檢查模式

Dart 程式以兩種模式執行,即 -

  • 檢查模式
  • 生產模式(預設)

建議在開發和測試期間以 **檢查模式** 執行 Dart VM,因為它會新增警告和錯誤以幫助開發和除錯過程。檢查模式會強制執行各種檢查,例如型別檢查等。要開啟檢查模式,在執行指令碼時,在指令碼檔名之前新增 -c 或 –-checked 選項。

但是,為了確保在執行指令碼時獲得性能優勢,建議在 **生產模式** 下執行指令碼。

考慮以下 **Test.dart** 指令碼檔案 -

void main() { 
   int n = "hello"; 
   print(n); 
} 

透過輸入以下內容執行指令碼 -

dart Test.dart

儘管存在型別不匹配,但指令碼仍成功執行,因為檢查模式已關閉。指令碼將產生以下輸出 -

hello

現在嘗試使用“- - checked”或“-c”選項執行指令碼 -

dart -c Test.dart 

或者,

dart - - checked Test.dart

Dart VM 將丟擲一個錯誤,指出存在型別不匹配。

Unhandled exception: 
type 'String' is not a subtype of type 'int' of 'n' where 
   String is from dart:core 
   int is from dart:core 
#0  main (file:///C:/Users/Administrator/Desktop/test.dart:3:9) 
#1  _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart :261) 
#2  _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

Dart 中的識別符號

識別符號是賦予程式中元素(如變數、函式等)的名稱。識別符號的規則如下 -

識別符號可以包含字元和數字。但是,識別符號不能以數字開頭。

  • 識別符號不能包含特殊符號,下劃線 (_) 或美元符號 ($) 除外。

  • 識別符號不能是關鍵字。

  • 它們必須是唯一的。

  • 識別符號區分大小寫。

  • 識別符號不能包含空格。

下表列出了一些有效和無效識別符號的示例 -

有效識別符號 無效識別符號
firstName Var
first_name first name
num1 first-name
$result 1number

Dart 中的關鍵字

關鍵字在語言上下文中具有特殊含義。下表列出了 Dart 中的一些關鍵字。

abstract 1 continue false new this
as 1 default final null throw
assert deferred 1 finally operator 1 true
async 2 do for part 1 try
async* 2 dynamic 1 get 1 rethrow typedef 1
await 2 else if return var
break enum implements 1 set 1 void
case export 1 import 1 static 1 while
catch external 1 in super with
class extends is switch yield 2
const factory 1

庫 1 同步* 2 生成* 2

空白和換行符

Dart 忽略程式中出現的空格、製表符和換行符。您可以在程式中自由使用空格、製表符和換行符,並且可以自由地以整潔一致的方式格式化和縮排程式,從而使程式碼易於閱讀和理解。

Dart 區分大小寫

Dart 區分大小寫。這意味著 Dart 區分大寫和小寫字元。

語句以分號結尾

每行指令稱為語句。每個 Dart 語句都必須以分號 (;) 結尾。一行可以包含多個語句。但是,這些語句必須用分號隔開。

Dart 中的註釋

註釋是提高程式可讀性的一種方法。註釋可用於包含有關程式的其他資訊,例如程式碼作者、有關函式/結構的提示等。註釋會被編譯器忽略。

Dart 支援以下型別的註釋 -

  • 單行註釋 ( // ) - "//" 和行尾之間的任何文字都被視為註釋

  • 多行註釋 (/* */) - 這些註釋可以跨越多行。

示例

// this is single line comment  
  
/* This is a   
   Multi-line comment  
*/ 

Dart 中的面向物件程式設計

Dart 是一種面向物件的語言。面向物件是一種軟體開發正規化,遵循現實世界的建模。面向物件將程式視為物件的集合,這些物件透過稱為方法的機制相互通訊。

  • 物件 - 物件是任何實體的即時表示。根據 Grady Brooch 的說法,每個物件都必須具有三個特徵 -

    • 狀態 - 由物件的屬性描述。

    • 行為 - 描述物件將如何行動。

    • 標識 - 一個唯一的值,將物件與一組類似的物件區分開來。

  • - 從 OOP 的角度來看,類是建立物件的藍圖。類封裝了物件的資料。

  • 方法 - 方法促進物件之間的通訊。

示例:Dart 和麵向物件

class TestClass {   
   void disp() {     
      print("Hello World"); 
   } 
}  
void main() {   
   TestClass c = new TestClass();   
   c.disp();  
}

以上示例定義了一個類 TestClass。該類有一個方法 disp()。該方法在終端上列印字串“Hello World”。new 關鍵字建立類的物件。該物件呼叫方法 disp()

程式碼應產生以下輸出 -

Hello World

Dart 程式設計 - 資料型別

程式語言最基本的特點之一是它支援的資料型別集。這些是在程式語言中可以表示和操作的值的型別。

Dart 語言支援以下型別 -

  • 數字
  • 字串
  • 布林值
  • 列表
  • 對映

數字

Dart 中的數字用於表示數字文字。Dart 數字有兩種型別 -

  • 整數 - 整數值表示非分數值,即沒有小數點的數值。例如,值“10”是整數。整數文字使用int關鍵字表示。

  • 雙精度浮點數 - Dart 也支援分數數值,即帶小數點的值。Dart 中的 Double 資料型別表示一個 64 位(雙精度)浮點數。例如,值“10.10”。double關鍵字用於表示浮點文字。

字串

字串表示字元序列。例如,如果您要儲存一些資料,例如姓名、地址等,則應使用字串資料型別。Dart 字串是 UTF-16 程式碼單元的序列。符文用於表示 UTF-32 程式碼單元的序列。

String關鍵字用於表示字串文字。字串值嵌入在單引號或雙引號中。

布林值

布林資料型別表示布林值 true 和 false。Dart 使用bool關鍵字表示布林值。

列表和對映

列表和對映資料型別用於表示物件的集合。列表是有序的物件組。Dart 中的 List 資料型別與其他程式語言中陣列的概念同義。對映資料型別表示一組鍵值對形式的值。dart:core庫分別透過預定義的 List 和 Map 類啟用這些集合的建立和操作。

動態型別

Dart 是一種可選型別語言。如果未顯式指定變數的型別,則變數的型別為dynamicdynamic關鍵字也可以用作型別註釋。

Dart 程式設計 - 變數

變數是“記憶體中命名的空間”,用於儲存值。換句話說,它充當程式中值的容器。變數名稱為識別符號。以下是識別符號的命名規則 -

  • 識別符號不能是關鍵字。

  • 識別符號可以包含字母和數字。

  • 識別符號不能包含空格和特殊字元,除了下劃線 (_) 和美元符號 ($)。

  • 變數名不能以數字開頭。

型別語法

必須在使用變數之前宣告它。Dart 使用 var 關鍵字來實現這一點。宣告變數的語法如下所示 -

var name = 'Smith';

Dart 中的所有變數都儲存對值的引用,而不是包含值本身。名為 name 的變數包含對值為“Smith”的 String 物件的引用。

Type Syntax

Dart 透過在變數名前新增資料型別來支援型別檢查。型別檢查確保變數僅儲存特定於資料型別的資料。相同的語法如下所示 -

String name = 'Smith'; 
int num = 10;

考慮以下示例 -

void main() { 
   String name = 1; 
}

以上程式碼段將產生警告,因為分配給變數的值與變數的資料型別不匹配。

輸出

Warning: A value of type 'String' cannot be assigned to a variable of type 'int' 

所有未初始化的變數的初始值均為 null。這是因為 Dart 將所有值視為物件。以下示例說明了這一點 -

void main() { 
   int num; 
   print(num); 
}

輸出

Null 

dynamic 關鍵字

未宣告靜態型別的變數隱式宣告為 dynamic。變數也可以使用 dynamic 關鍵字代替 var 關鍵字進行宣告。

以下示例說明了這一點。

void main() { 
   dynamic x = "tom"; 
   print(x);  
}

輸出

tom

final 和 const

finalconst關鍵字用於宣告常量。Dart 阻止修改使用 final 或 const 關鍵字宣告的變數的值。這些關鍵字可以與變數的資料型別一起使用,也可以代替var關鍵字使用。

const關鍵字用於表示編譯時常量。使用const關鍵字宣告的變數隱式為 final。

語法:final 關鍵字

final variable_name

final data_type  variable_name

語法:const 關鍵字

const variable_name

const data_type variable_name

示例 – final 關鍵字

void main() { 
   final val1 = 12; 
   print(val1); 
}

輸出

12

示例 – const 關鍵字

void main() { 
   const pi = 3.14; 
   const area = pi*12*12; 
   print("The output is ${area}"); 
}

以上示例使用const關鍵字聲明瞭兩個常量piareaarea變數的值是編譯時常量。

輸出

The output is 452.15999999999997

注意 - 只有const變數才能用於計算編譯時常量。編譯時常量是在編譯時確定其值的常量

示例

如果嘗試修改使用final或 const 關鍵字宣告的變數,Dart 會丟擲異常。以下示例說明了這一點 -

void main() { 
   final v1 = 12; 
   const v2 = 13; 
   v2 = 12; 
}

上面給出的程式碼將丟擲以下錯誤作為輸出 -

Unhandled exception: 
cannot assign to final variable 'v2='.  
NoSuchMethodError: cannot assign to final variable 'v2=' 
#0  NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:178) 
#1      main (file: Test.dart:5:3) 
#2    _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:261) 
#3    _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

Dart 程式設計 - 運算子

表示式是一種特殊的語句,它計算出一個值。每個表示式都由 -

  • 運算元 - 表示資料

  • 運算子 - 定義如何處理運算元以生成值。

考慮以下表達式 – "2 + 3"。在此表示式中,2 和 3 是運算元,符號 "+"(加號)是運算子

在本章中,我們將討論 Dart 中可用的運算子。

  • 算術運算子
  • 相等和關係運算符
  • 型別測試運算子
  • 按位運算子
  • 賦值運算子
  • 邏輯運算子

算術運算子

下表顯示了 Dart 支援的算術運算子。

顯示示例

序號 運算子和含義
1 +

2

3 -expr

一元減號,也稱為否定(反轉表示式的符號)

4 *

5 /

6 ~/

除,返回整數結果

7 %

獲取整數除法的餘數(模)

8 ++

遞增

9 --

遞減

相等和關係運算符

關係運算符測試或定義兩個實體之間關係的型別。關係運算符返回布林值,即 true/false。

假設 A 的值為 10,B 的值為 20。

顯示示例

運算子 描述 示例
> 大於 (A > B) 為 False
< 小於 (A < B) 為 True
>= 大於或等於 (A >= B) 為 False
<= 小於或等於 (A <= B) 為 True
== 相等 (A==B) 為 False
!= 不相等 (A!=B) 為 True

型別測試運算子

這些運算子對於在執行時檢查型別非常方便。

顯示示例

運算子 含義
is 如果物件具有指定的型別,則為 True
is! 如果物件具有指定的型別,則為 False

按位運算子

下表列出了 Dart 中可用的按位運算子及其作用 -

顯示示例

運算子 描述 示例
按位與 a & b 在每個位位置返回 1,對於這兩個運算元的相應位均為 1。
按位或 a | b 在每個位位置返回 1,對於這兩個運算元的相應位為 1 或兩者均為 1。
按位異或 a ^ b 在每個位位置返回 1,對於這兩個運算元的相應位為 1,但不是兩者均為 1。
按位非 ~ a 反轉其運算元的位。
左移 a ≪ b 將 a 的二進位制表示形式向左移動 b (< 32) 位,從右側移入零。
帶符號右移 a ≫ b 將 a 的二進位制表示形式向右移動 b (< 32) 位,丟棄移出的位。

賦值運算子

下表列出了 Dart 中可用的賦值運算子。

顯示示例

序號 運算子和描述
1 =(簡單賦值)

將右側運算元的值賦給左側運算元

示例:C = A + B 會將 A + B 的值賦給 C

2 ??=

僅當變數為空時才賦值

3 +=(加法和賦值)

它將右側運算元加到左側運算元,並將結果賦給左側運算元。

示例:C += A 等價於 C = C + A

4 ─=(減法和賦值)

它從左側運算元中減去右側運算元,並將結果賦給左側運算元。

示例:C -= A 等價於 C = C – A

5 *=(乘法和賦值)

它將右側運算元乘以左側運算元,並將結果賦給左側運算元。

示例:C *= A 等價於 C = C * A

6 /=(除法和賦值)

它將左側運算元除以右側運算元,並將結果賦給左側運算元。

注意 - 位運算子也適用相同的邏輯,因此它們將變為 ≪=、≫=、≫=、≫=、|= 和 ^=。

邏輯運算子

邏輯運算子用於組合兩個或多個條件。邏輯運算子返回布林值。假設變數 A 的值為 10,B 的值為 20。

顯示示例

運算子 描述 示例
&&

- 只有當所有指定的表示式都返回 true 時,運算子才返回 true

(A > 10 && B > 10) 為假。
||

- 如果指定的表示式中至少有一個返回 true,則運算子返回 true

(A > 10 || B > 10) 為真。
!

- 運算子返回表示式的結果的反值。例如:!(7>5) 返回 false

!(A > 10) 為真。

條件表示式

Dart 有兩個運算子,允許您評估可能需要 ifelse 語句的表示式 -

condition ? expr1 : expr2

如果 condition 為真,則表示式計算 expr1(並返回其值);否則,它計算並返回 expr2 的值。

expr1 ?? expr2

如果 expr1 不為 null,則返回其值;否則,計算並返回 expr2 的值

示例

以下示例顯示瞭如何在 Dart 中使用條件表示式 -

void main() { 
   var a = 10; 
   var res = a > 12 ? "value greater than 10":"value lesser than or equal to 10"; 
   print(res); 
} 

它將產生以下輸出 -

value lesser than or equal to 10

示例

讓我們看另一個例子 -

void main() { 
   var a = null; 
   var b = 12; 
   var res = a ?? b; 
   print(res); 
}

它將產生以下輸出 -

12

Dart 程式設計 - 迴圈

有時,某些指令需要重複執行。迴圈是執行此操作的理想方法。迴圈表示必須重複的一組指令。在迴圈的上下文中,重複稱為迭代

下圖說明了迴圈的分類 -

Classification Of Loops

讓我們從確定迴圈開始討論。迭代次數確定/固定的迴圈稱為確定迴圈

序號 迴圈 & 描述
1 for 迴圈

for 迴圈是確定迴圈的一種實現。for 迴圈執行程式碼塊指定次數。它可以用於迭代一組固定的值,例如陣列

2 for...in 迴圈

for...in 迴圈用於迴圈遍歷物件的屬性。

接下來,讓我們討論不確定迴圈。當迴圈的迭代次數不確定或未知時,使用不確定迴圈。不確定迴圈可以使用 -

序號 迴圈 & 描述
1 while 迴圈

while 迴圈每次指定的條件計算結果為 true 時都執行指令。換句話說,迴圈在執行程式碼塊之前評估條件。

2 do…while 迴圈

do…while 迴圈類似於 while 迴圈,只是 do...while 迴圈在第一次執行迴圈時不評估條件。

現在讓我們繼續討論 Dart 的迴圈控制語句

序號 控制語句 & 描述
1 break 語句

break 語句用於將控制權從構造中取出。在迴圈中使用break 會導致程式退出迴圈。以下是break 語句的示例。

2 continue 語句

continue 語句跳過當前迭代中的後續語句,並將控制權返回到迴圈的開頭。

使用標籤控制流程

標籤只是一個後跟冒號 (:) 的識別符號,應用於語句或程式碼塊。標籤可以與breakcontinue 一起使用以更精確地控制流程。

‘continue’‘break’ 語句與其標籤名稱之間不允許換行。此外,標籤名稱和關聯迴圈之間也不應有任何其他語句。

示例:帶 Break 的標籤

void main() { 
   outerloop: // This is the label name 
   
   for (var i = 0; i < 5; i++) { 
      print("Innerloop: ${i}"); 
      innerloop: 
      
      for (var j = 0; j < 5; j++) { 
         if (j > 3 ) break ; 
         
         // Quit the innermost loop 
         if (i == 2) break innerloop; 
         
         // Do the same thing 
         if (i == 4) break outerloop; 
         
         // Quit the outer loop 
         print("Innerloop: ${j}"); 
      } 
   } 
}

在成功執行上述程式碼後,將顯示以下輸出

Innerloop: 0
Innerloop: 0
Innerloop: 1
Innerloop: 2
Innerloop: 3
Innerloop: 1
Innerloop: 0
Innerloop: 1
Innerloop: 2
Innerloop: 3
Innerloop: 2
Innerloop: 3
Innerloop: 0
Innerloop: 1
Innerloop: 2
Innerloop: 3
Innerloop: 4

示例:帶 continue 的標籤

void main() { 
   outerloop: // This is the label name 
   
   for (var i = 0; i < 3; i++) { 
      print("Outerloop:${i}"); 
      
      for (var j = 0; j < 5; j++) { 
         if (j == 3){ 
            continue outerloop; 
         } 
         print("Innerloop:${j}"); 
      } 
   } 
}

在成功執行上述程式碼後,將顯示以下輸出。

Outerloop: 0 
Innerloop: 0 
Innerloop: 1 
Innerloop: 2 

Outerloop: 1 
Innerloop: 0 
Innerloop: 1 
Innerloop: 2 

Outerloop: 2 
Innerloop: 0 
Innerloop: 1 
Innerloop: 2 

Dart 程式設計 - 條件語句

條件/決策構造在執行指令之前評估條件。

Decision Making

Dart 中的條件構造在以下表格中分類。

序號 語句 & 描述
1 if 語句

if 語句由一個布林表示式後跟一個或多個語句組成。

2 If...Else 語句

if 後面可以跟一個可選的else 塊。如果if 塊測試的布林表示式計算結果為 false,則將執行else 塊。

3 else…if 梯

else…if 梯用於測試多個條件。以下是相同的語法。

4 switch…case 語句

switch 語句評估表示式,將表示式的值與 case 子句匹配,並執行與該 case 關聯的語句。

Dart 程式設計 - 數字

Dart 數字可以分類為 -

  • int - 任意大小的整數。int 資料型別用於表示整數。

  • double - 64 位(雙精度)浮點數,如 IEEE 754 標準所指定。double 資料型別用於表示小數

num 型別由intdouble 型別繼承。dart core 庫允許對數值執行許多操作。

宣告數字的語法如下所示 -

int var_name;      // declares an integer variable 
double var_name;   // declares a double variable 

示例

void main() {
   // declare an integer
   int num1 = 10;             
     
   // declare a double value
   double num2 = 10.50;  

   // print the values
   print(num1);
   print(num2);
}

它將產生以下輸出 -

10 
10.5 

注意 - 如果將小數賦值給整數變數,則Dart VM 將丟擲異常。

解析

parse() 靜態函式允許將包含數字字面量的字串解析為數字。以下說明演示了相同 -

void main() { 
   print(num.parse('12')); 
   print(num.parse('10.91')); 
}

以上程式碼將產生以下輸出 -

12 
10.91

如果傳遞給 parse() 函式的值不是數字,則 parse 函式會丟擲 FormatException。以下程式碼顯示瞭如何將字母數字值傳遞給parse() 函式。

示例

void main() { 
   print(num.parse('12A')); 
   print(num.parse('AAAA')); 
}

以上程式碼將產生以下輸出 -

Unhandled exception: 
FormatException: 12A 
#0 num.parse (dart:core/num.dart:446) 
#1 main (file:///D:/Demos/numbers.dart:4:13) 
#2 _startIsolate.<anonymous closure> (dart:isolatepatch/isolate_patch.dart:261) 
#3 _RawReceivePortImpl._handleMessage (dart:isolatepatch/isolate_patch.dart:148)

數字屬性

下表列出了 Dart 數字支援的屬性。

序號 屬性 & 描述
1 hashcode

返回數值的雜湊碼。

2 isFinite

如果數字是有限的,則為真;否則為假。

3 isInfinite

如果數字是正無窮大或負無窮大,則為真;否則為假。

4 isNan

如果數字是雙精度非數字值,則為真;否則為假。

5 isNegative

如果數字為負,則為真;否則為假。

6 sign

根據數字的符號和數值返回負一、零或正一。

7 isEven

如果數字是偶數,則返回 true。

8 isOdd

如果數字是奇數,則返回 true。

數字方法

下面列出了數字支援的一些常用方法 -

序號 方法 & 描述
1 abs

返回數字的絕對值。

2 ceil

返回不小於數字的最小整數。

3 compareTo

將此與其他數字進行比較。

4 Floor

返回不大於當前數字的最大整數。

5 remainder

返回兩個數字相除後的截斷餘數。

6 Round

返回最接近當前數字的整數。

7 toDouble

返回數字的雙精度等效值。

8 toInt

返回數字的整數等效值。

9 toString

返回數字的字串等效表示形式。

10 truncate

丟棄任何小數位後返回一個整數。

Dart 程式設計 - 字串

String 資料型別表示字元序列。Dart 字串是 UTF 16 程式碼單元的序列。

Dart 中的字串值可以使用單引號或雙引號或三引號表示。單行字串使用單引號或雙引號表示。三引號用於表示多行字串。

在 Dart 中表示字串值的語法如下所示 -

語法

String  variable_name = 'value'  

OR  

String  variable_name = ''value''  

OR  

String  variable_name = '''line1 
line2'''  

OR  

String  variable_name= ''''''line1 
line2''''''

以下示例說明了在 Dart 中使用 String 資料型別。

void main() { 
   String str1 = 'this is a single line string'; 
   String str2 = "this is a single line string"; 
   String str3 = '''this is a multiline line string'''; 
   String str4 = """this is a multiline line string"""; 
   
   print(str1);
   print(str2); 
   print(str3); 
   print(str4); 
}

它將產生以下輸出 -

this is a single line string 
this is a single line string 
this is a multiline line string 
this is a multiline line string 

字串是不可變的。但是,字串可以進行各種操作,並且結果字串可以儲存為新值。

字串插值

透過將值附加到靜態字串來建立新字串的過程稱為連線插值。換句話說,它是將一個字串新增到另一個字串的過程。

加號運算子 (+) 是連線/插值字串的常用機制。

示例 1

void main() { 
   String str1 = "hello"; 
   String str2 = "world"; 
   String res = str1+str2; 
   
   print("The concatenated string : ${res}"); 
}

它將產生以下輸出 -

The concatenated string : Helloworld

示例 2

您可以使用 "${}" 用於在字串中插值 Dart 表示式的值。以下示例說明了相同。

void main() { 
   int n=1+1; 
   
   String str1 = "The sum of 1 and 1 is ${n}"; 
   print(str1); 
   
   String str2 = "The sum of 2 and 2 is ${2+2}"; 
   print(str2); 
}

它將產生以下輸出 -

The sum of 1 and 1 is 2 
The sum of 2 and 2 is 4

字串屬性

下表中列出的屬性都是隻讀的。

序號 屬性 & 描述
1 codeUnits

返回此字串的 UTF-16 程式碼單元的不可修改列表。

2 isEmpty

如果此字串為空,則返回 true。

3 Length

返回字串的長度,包括空格、製表符和換行符。

操作字串的方法

dart: core 庫中的 String 類還提供用於操作字串的方法。其中一些方法如下所示 -

序號 方法 & 描述
1 toLowerCase()

將此字串中的所有字元轉換為小寫。

2 toUpperCase()

將此字串中的所有字元轉換為大寫。

3 trim()

返回沒有前導和尾隨空格的字串。

4 compareTo()

將此物件與另一個物件進行比較。

5 replaceAll()

用給定值替換與指定模式匹配的所有子字串。

6 split()

在指定分隔符的匹配項處分割字串,並返回子字串列表。

7 substring()

返回此字串的子字串,該子字串從 startIndex(包含)擴充套件到 endIndex(不包含)。

8 toString()

返回此物件的字串表示形式。

9 codeUnitAt()

返回給定索引處的 16 位 UTF-16 程式碼單元。

Dart 程式設計 - 布林值

Dart 為布林資料型別提供了內建支援。DART 中的布林資料型別僅支援兩個值 - true 和 false。關鍵字 bool 用於在 DART 中表示布林文字。

在 DART 中宣告布林變數的語法如下所示:

bool var_name = true;  
OR  
bool var_name = false 

示例

void main() { 
   bool test; 
   test = 12 > 5; 
   print(test); 
}

它將產生以下輸出 -

true 

示例

與 JavaScript 不同,布林資料型別只識別文字 true 為真。任何其他值都被視為假。請考慮以下示例:

var str = 'abc'; 
if(str) { 
   print('String is not empty'); 
} else { 
   print('Empty String'); 
} 

如果在 JavaScript 中執行上述程式碼片段,則會列印訊息“字串不為空”,因為如果字串不為空,則 if 結構將返回 true。

但是,在 Dart 中,str 被轉換為false,因為 str != true。因此,程式碼片段將列印訊息“空字串”(在未經檢查模式下執行時)。

示例

如果在已檢查模式下執行上述程式碼片段,則會丟擲異常。下面說明了這一點:

void main() { 
   var str = 'abc'; 
   if(str) { 
      print('String is not empty'); 
   } else { 
      print('Empty String'); 
   } 
}

它將在已檢查模式下產生以下輸出

Unhandled exception: 
type 'String' is not a subtype of type 'bool' of 'boolean expression' where 
   String is from dart:core 
   bool is from dart:core  
#0 main (file:///D:/Demos/Boolean.dart:5:6) 
#1 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:261) 
#2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

它將在未經檢查模式下產生以下輸出

Empty String

注意 - WebStorm IDE 預設以已檢查模式執行。

Dart 程式設計 - 列表

程式設計中一個非常常用的集合是陣列。Dart 以List物件的形勢表示陣列。List只是一個物件的排序組。dart:core庫提供了 List 類,使您可以建立和操作列表。

Dart 中列表的邏輯表示如下所示:

Logical Representation of a List
  • test_list - 是引用集合的識別符號。

  • 列表包含值 12、13 和 14。儲存這些值的記憶體塊稱為元素

  • List 中的每個元素都由一個唯一的數字標識,稱為索引。索引從開始,擴充套件到n-1,其中n是 List 中元素的總數。索引也稱為下標

列表可以分類為:

  • 固定長度列表
  • 可增長列表

現在讓我們詳細討論這兩種型別的列表

固定長度列表

固定長度列表的長度在執行時不能更改。建立固定長度列表的語法如下所示:

步驟 1 - 宣告列表

宣告固定長度列表的語法如下所示:

var list_name = new List(initial_size)

上述語法建立一個指定大小的列表。列表在執行時不能增長或縮小。任何嘗試調整列表大小的操作都將導致異常。

步驟 2 - 初始化列表

初始化列表的語法如下所示:

lst_name[index] = value;

示例

void main() { 
   var lst = new List(3); 
   lst[0] = 12; 
   lst[1] = 13; 
   lst[2] = 11; 
   print(lst); 
}

它將產生以下輸出 -

[12, 13, 11]

可增長列表

可增長列表的長度可以在執行時更改。宣告和初始化可增長列表的語法如下所示:

步驟 1 - 宣告列表

var list_name = [val1,val2,val3]   
--- creates a list containing the specified values  
OR  
var list_name = new List() 
--- creates a list of size zero 

步驟 2 - 初始化列表

索引/下標用於引用應填充值的元素。初始化列表的語法如下所示:

list_name[index] = value;

示例

以下示例顯示瞭如何建立包含 3 個元素的列表。

void main() { 
   var num_list = [1,2,3]; 
   print(num_list); 
}

它將產生以下輸出 -

[1, 2, 3]

示例

以下示例使用空 List() 建構函式建立了一個零長度列表。List類中的add()函式用於動態地向列表中新增元素。

void main() { 
   var lst = new List(); 
   lst.add(12); 
   lst.add(13); 
   print(lst); 
} 

它將產生以下輸出 -

[12, 13] 

列表屬性

下表列出了dart:core 庫List類的一些常用屬性。

序號 方法 & 描述
1 first

返回列表中的第一個元素。

2 isEmpty

如果集合沒有元素,則返回 true。

3 isNotEmpty

如果集合至少包含一個元素,則返回 true。

4 length

返回列表的大小。

5 last

返回列表中的最後一個元素。

6 reversed

返回一個可迭代物件,其中包含按反序排列的列表值。

7 Single

檢查列表是否只有一個元素並返回它。

Dart 程式設計 - 列表(基本操作)

在本章中,我們將討論如何對列表執行一些基本操作,例如:

序號 基本操作和說明
1 將元素插入列表

可變列表可以在執行時動態增長。List.add()函式將指定值附加到 List 的末尾,並返回一個修改後的 List 物件。

2 更新列表

Dart 中的列表可以透過以下方式更新:

3 刪除列表項

dart:core 庫中 List 類支援的以下函式可用於刪除 List 中的專案。

Dart 程式設計 - 對映

Map 物件是一個簡單的鍵/值對。Map 中的鍵和值可以是任何型別。Map 是一個動態集合。換句話說,Map可以在執行時增長和縮小。

Map 可以透過兩種方式宣告:

  • 使用 Map 字面量
  • 使用 Map 建構函式

使用 Map 字面量宣告 Map

要使用 Map 字面量宣告 Map,您需要將鍵值對括在一對花括號"{ }"中。

以下是其語法

var identifier = { key1:value1, key2:value2 [,…..,key_n:value_n] }

使用 Map 建構函式宣告 Map

要使用 Map 建構函式宣告 Map,我們需要兩個步驟。首先,宣告 Map,其次,初始化 Map。

宣告 Map語法如下:

var identifier = new Map()

現在,使用以下語法初始化 Map

map_name[key] = value

示例:Map 字面量

void main() { 
   var details = {'Usrname':'tom','Password':'pass@123'}; 
   print(details); 
}

它將產生以下輸出 -

{Usrname: tom, Password: pass@123}

示例:在執行時向 Map 字面量新增值

void main() { 
   var details = {'Usrname':'tom','Password':'pass@123'}; 
   details['Uid'] = 'U1oo1'; 
   print(details); 
} 

它將產生以下輸出 -

{Usrname: tom, Password: pass@123, Uid: U1oo1}

示例:Map 建構函式

void main() { 
   var details = new Map(); 
   details['Usrname'] = 'admin'; 
   details['Password'] = 'admin@123'; 
   print(details); 
} 

它將產生以下輸出 -

{Usrname: admin, Password: admin@123}

注意 - Map 值可以是任何物件,包括 NULL。

Map – 屬性

dart:core 包中的Map類定義了以下屬性:

序號 屬性 & 描述
1 Keys

返回表示鍵的可迭代物件

2 Values

返回表示值的可迭代物件

3 Length

返回 Map 的大小

4 isEmpty

如果 Map 是一個空 Map,則返回 true

5 isNotEmpty

如果 Map 是一個空 Map,則返回 true

Map - 函式

以下是 Dart 中用於操作 Map 的常用函式。

序號 函式名稱和說明
1 addAll()

將 other 的所有鍵值對新增到此 Map 中。

2 clear()

從 Map 中刪除所有對。

3 remove()

如果存在,則從 Map 中刪除鍵及其關聯的值。

4 forEach()

將 f 應用於 Map 的每個鍵值對。

Dart 程式設計 - 符號

Dart 中的符號是不透明的,是用於從庫中反射元資料的動態字串名稱。簡而言之,符號是儲存人類可讀字串和計算機使用的最佳化字串之間關係的一種方式。

反射是一種在執行時獲取型別元資料(例如類中的方法數量、它具有的建構函式數量或函式中的引數數量)的機制。您甚至可以呼叫在執行時載入的型別的某個方法。

在 Dart 中,dart:mirrors包中提供了特定於反射的類。此庫適用於 Web 應用程式和命令列應用程式。

語法

Symbol obj = new Symbol('name');  
// expects a name of class or function or library to reflect 

name必須是有效的公共 Dart 成員名稱、公共建構函式名稱或庫名稱。

示例

請考慮以下示例。程式碼在foo_lib庫中聲明瞭一個類Foo。該類定義了方法m1、m2m3

Foo.dart

library foo_lib;   
// libarary name can be a symbol   

class Foo {         
   // class name can be a symbol  
   m1() {        
      // method name can be a symbol 
      print("Inside m1"); 
   } 
   m2() { 
      print("Inside m2"); 
   } 
   m3() { 
      print("Inside m3"); 
   } 
}

以下程式碼載入Foo.dart庫並搜尋 Foo 類,藉助 Symbol 型別。由於我們正在從上述庫中反射元資料,因此程式碼匯入dart:mirrors庫。

FooSymbol.dart

import 'dart:core'; 
import 'dart:mirrors'; 
import 'Foo.dart';  

main() { 
   Symbol lib = new Symbol("foo_lib");   
   //library name stored as Symbol 
   
   Symbol clsToSearch = new Symbol("Foo");  
   // class name stored as Symbol  
   
   if(checkIf_classAvailableInlibrary(lib, clsToSearch))  
   // searches Foo class in foo_lib library 
      print("class found.."); 
}  
   
bool checkIf_classAvailableInlibrary(Symbol libraryName, Symbol className) { 
   MirrorSystem mirrorSystem = currentMirrorSystem(); 
   LibraryMirror libMirror = mirrorSystem.findLibrary(libraryName); 
      
   if (libMirror != null) { 
      print("Found Library"); 
      print("checkng...class details.."); 
      print("No of classes found is : ${libMirror.declarations.length}"); 
      libMirror.declarations.forEach((s, d) => print(s));  
         
      if (libMirror.declarations.containsKey(className)) return true; 
      return false; 
   } 
}

請注意,行 libMirror.declarations.forEach((s, d) => print(s)); 將在執行時遍歷庫中的每個宣告,並列印宣告作為Symbol型別。

此程式碼應產生以下輸出

Found Library 
checkng...class details.. 
No of classes found is : 1 
Symbol("Foo") // class name displayed as symbol  
class found. 

示例:顯示類的例項方法的數量

現在讓我們考慮顯示類中的例項方法的數量。預定義類ClassMirror幫助我們實現了這一點。

import 'dart:core'; 
import 'dart:mirrors'; 
import 'Foo.dart';  

main() { 
   Symbol lib = new Symbol("foo_lib"); 
   Symbol clsToSearch = new Symbol("Foo");  
   reflect_InstanceMethods(lib, clsToSearch); 
}  
void reflect_InstanceMethods(Symbol libraryName, Symbol className) { 
   MirrorSystem mirrorSystem = currentMirrorSystem(); 
   LibraryMirror libMirror = mirrorSystem.findLibrary(libraryName); 
   
   if (libMirror != null) { 
      print("Found Library"); 
      print("checkng...class details.."); 
      print("No of classes found is : ${libMirror.declarations.length}"); 
      libMirror.declarations.forEach((s, d) => print(s));  
      
      if (libMirror.declarations.containsKey(className)) print("found class");
      ClassMirror classMirror = libMirror.declarations[className]; 
      
      print("No of instance methods found is ${classMirror.instanceMembers.length}");
      classMirror.instanceMembers.forEach((s, v) => print(s)); 
   } 
}    

此程式碼應產生以下輸出

Found Library 
checkng...class details.. 
No of classes found is : 1 
Symbol("Foo") 
found class 
No of instance methods found is 8 
Symbol("==") 
Symbol("hashCode") 
Symbol("toString") 
Symbol("noSuchMethod") 
Symbol("runtimeType") 
Symbol("m1") 
Symbol("m2") 
Symbol("m3")

將 Symbol 轉換為字串

您可以使用MirrorSystem類將儲存在符號中的型別(如類或庫)的名稱轉換回字串。以下程式碼顯示瞭如何將符號轉換為字串。

import 'dart:mirrors'; 
void main(){ 
   Symbol lib = new Symbol("foo_lib"); 
   String name_of_lib = MirrorSystem.getName(lib); 
   
   print(lib); 
   print(name_of_lib); 
}

它應產生以下輸出

Symbol("foo_lib")   

foo_lib     

Dart 程式設計 - 字串碼點

字串是一系列字元。Dart 將字串表示為一系列 Unicode UTF-16 程式碼單元。Unicode 是一種格式,為每個字母、數字和符號定義一個唯一的數值。

由於 Dart 字串是一系列 UTF-16 程式碼單元,因此字串中的 32 位 Unicode 值使用特殊語法表示。rune是表示 Unicode 程式碼點的整數。

dart:core庫中的 String 類提供了訪問rune的機制。可以透過三種方式訪問字串程式碼單元/rune:

  • 使用 String.codeUnitAt() 函式
  • 使用 String.codeUnits 屬性
  • 使用 String.runes 屬性

String.codeUnitAt() 函式

可以透過其索引訪問字串中的程式碼單元。返回給定索引處的 16 位 UTF-16 程式碼單元。

語法

String.codeUnitAt(int index);

示例

import 'dart:core'; 
void main(){ 
   f1(); 
} 
f1() { 
   String x = 'Runes'; 
   print(x.codeUnitAt(0)); 
}

它將產生以下輸出 -

82

String.codeUnits 屬性

此屬性返回指定字串的 UTF-16 程式碼單元的不可修改列表。

語法

String. codeUnits;

示例

import 'dart:core';  
void main(){ 
   f1(); 
}  
f1() { 
   String x = 'Runes'; 
   print(x.codeUnits); 
} 

它將產生以下輸出 -

[82, 117, 110, 101, 115]

String.runes 屬性

此屬性返回此string.Runes的可迭代 Unicode 程式碼點。擴充套件了可迭代。

語法

String.runes

示例

void main(){ 
   "A string".runes.forEach((int rune) { 
      var character=new String.fromCharCode(rune); 
      print(character); 
   });  
} 

它將產生以下輸出 -

A 
s 
t 
r 
i 
n 
g

Unicode 程式碼點通常表示為\uXXXX,其中 XXXX 是一個 4 位十六進位制值。要指定多於或少於 4 個十六進位制數字,請將值放在花括號中。可以使用 dart:core 庫中 Runes 類的建構函式來實現相同的功能。

示例

main() { 
   Runes input = new Runes(' \u{1f605} '); 
   print(new String.fromCharCodes(input)); 
}  

它將產生以下輸出 -

Runes

Dart 程式設計 - 列舉

列舉用於定義命名常量值。列舉型別使用enum關鍵字宣告。

語法

enum enum_name {  
   enumeration list 
}

其中,

  • enum_name指定列舉型別名稱
  • enumeration list是識別符號的逗號分隔列表

列舉列表中的每個符號都代表一個整數,比它前面的符號大 1。預設情況下,第一個列舉符號的值為 0。

例如

enum Status { 
   none, 
   running, 
   stopped, 
   paused 
}

示例

enum Status { 
   none, 
   running, 
   stopped, 
   paused 
}  
void main() { 
   print(Status.values); 
   Status.values.forEach((v) => print('value: $v, index: ${v.index}'));
   print('running: ${Status.running}, ${Status.running.index}'); 
   print('running index: ${Status.values[1]}'); 
}

它將產生以下輸出 -

[Status.none, Status.running, Status.stopped, Status.paused] 
value: Status.none, index: 0 
value: Status.running, index: 1 
value: Status.stopped, index: 2 
value: Status.paused, index: 3 
running: Status.running, 1 
running index: Status.running 

Dart 程式設計 - 函式

函式是可讀、可維護和可重用程式碼的構建塊。函式是一組用於執行特定任務的語句。函式將程式組織成邏輯程式碼塊。函式定義後,可以呼叫它們來訪問程式碼。這使得程式碼可重用。此外,函式使程式程式碼易於閱讀和維護。

函式宣告告訴編譯器函式的名稱、返回型別和引數。函式定義提供了函式的實際主體。

序號 函式和說明
1 定義函式

函式定義指定特定任務將如何完成。

2 呼叫函式

必須呼叫函式才能執行它。

3 返回函式

函式也可以將值與控制一起返回給呼叫方。

4 引數化函式

引數是將值傳遞給函式的一種機制。

可選引數

當不需要強制傳遞引數以執行函式時,可以使用可選引數。可以透過在其名稱後附加問號來將引數標記為可選。可選引數應設定為函式中的最後一個引數。

Dart 中有三種類型的可選引數:

序號 引數和說明
1 可選位置引數

要指定可選位置引數,請使用方括號 []。

2 可選命名引數

與位置引數不同,在傳遞值時必須指定引數的名稱。花括號 {} 可用於指定可選命名引數。

3 具有預設值的可選引數

函式引數也可以分配預設值。但是,這些引數也可以顯式地傳遞值。

遞迴 Dart 函式

遞迴是一種透過讓函式重複呼叫自身直到獲得結果來迭代操作的技術。當您需要在迴圈中從函式內部重複呼叫相同的函式並使用不同的引數時,最適合應用遞迴。

示例

void main() { 
   print(factorial(6));
}  
factorial(number) { 
   if (number <= 0) {         
      // termination case 
      return 1; 
   } else { 
      return (number * factorial(number - 1));    
      // function invokes itself 
   } 
}   

它應產生以下輸出

720

Lambda 函式

Lambda 函式是一種表示函式的簡潔機制。這些函式也稱為箭頭函式。

語法

[return_type]function_name(parameters)=>expression;

示例

void main() { 
   printMsg(); 
   print(test()); 
}  
printMsg()=>
print("hello"); 

int test()=>123;                       
// returning function

它應產生以下輸出

hello 123 

Dart 程式設計 - 介面

介面定義了任何實體必須遵守的語法。介面定義了一組物件上可用的方法。Dart 沒有宣告介面的語法。在 Dart 中,類宣告本身就是介面。

應該使用 implements 關鍵字才能使用介面。實現類必須提供所有實現介面函式的具體實現,這是強制性的。換句話說,一個類必須重新定義它希望實現的介面中的每個函式。

語法:實現介面

class identifier implements interface_name

示例

在下面的程式中,我們聲明瞭一個類PrinterConsolePrinter 類實現了Printer 類的隱式介面宣告。main 函式使用new 關鍵字建立了ConsolePrinter 類的一個物件。此物件用於呼叫ConsolePrinter 類中定義的函式print_data

void main() { 
   ConsolePrinter cp= new ConsolePrinter(); 
   cp.print_data(); 
}  
class Printer { 
   void print_data() { 
      print("__________Printing Data__________"); 
   } 
}  
class ConsolePrinter implements Printer { 
   void print_data() {  
      print("__________Printing to Console__________"); 
   } 
} 

它應產生以下輸出

__________Printing to Console__________

實現多個介面

一個類可以實現多個介面。介面之間用逗號分隔。相同的語法如下所示:

class identifier implements interface-1,interface_2,interface_4…….

以下示例演示瞭如何在 Dart 中實現多個介面:

void main() { 
   Calculator c = new Calculator(); 
   print("The gross total : ${c.ret_tot()}"); 
   print("Discount :${c.ret_dis()}"); 
}  
class Calculate_Total { 
   int ret_tot() {} 
}  
class Calculate_Discount { 
   int ret_dis() {} 
}
class Calculator  implements Calculate_Total,Calculate_Discount { 
   int ret_tot() { 
      return 1000; 
   } 
   int ret_dis() { 
      return 50; 
   } 
}

它應產生以下輸出

The gross total: 1000 
Discount:50 

Dart 程式設計 - 類

Dart 是一種面向物件的語言。它支援面向物件程式設計特性,如類、介面等。從 OOP 的角度來看,是建立物件的藍圖。封裝了物件的資料。Dart 為此概念提供了內建支援,稱為

宣告類

使用class 關鍵字在 Dart 中宣告。類定義以關鍵字 class 開頭,後跟類名;以及用一對花括號括起來的類體。相同的語法如下所示:

語法

class class_name {  
   <fields> 
   <getters/setters> 
   <constructors> 
   <functions> 
}

class 關鍵字後跟類名。命名類時必須考慮識別符號的規則。

類定義可以包含以下內容:

  • 欄位 - 欄位是在類中宣告的任何變數。欄位表示與物件相關的資料。

  • Setter 和 Getter - 允許程式初始化和檢索類的欄位的值。每個類都關聯一個預設的 getter/setter。但是,可以透過顯式定義 setter/getter 來覆蓋預設的 getter/setter。

  • 建構函式 - 負責為類的物件分配記憶體。

  • 函式 - 函式表示物件可以執行的操作。它們有時也稱為方法。

這些元件組合在一起稱為類的資料成員

示例:宣告一個類

class Car {  
   // field 
   String engine = "E1001";  
   
   // function 
   void disp() { 
      print(engine); 
   } 
}

此示例聲明瞭一個類Car。該類有一個名為engine 的欄位。disp() 是一個簡單的函式,用於列印欄位engine 的值。

建立類的例項

要建立類的例項,請使用new 關鍵字後跟類名。相同的語法如下所示:

語法

var object_name = new class_name([ arguments ])
  • new 關鍵字負責例項化。

  • 表示式的右側呼叫建構函式。如果建構函式是引數化的,則應向其傳遞值。

示例:例項化一個類

var obj = new Car("Engine 1")

訪問屬性和函式

可以透過物件訪問類的屬性和函式。使用“.” 點表示法(稱為句點)來訪問類的成員資料。

//accessing an attribute 
obj.field_name  

//accessing a function 
obj.function_name()

示例

請檢視以下示例,瞭解如何在 Dart 中訪問屬性和函式:

void main() { 
   Car c= new Car(); 
   c.disp(); 
}  
class Car {  
   // field 
   String engine = "E1001";  
   
   // function 
   void disp() { 
      print(engine); 
   } 
}

以上程式碼的輸出如下:

E1001

Dart 建構函式

建構函式是類的特殊函式,負責初始化類的變數。Dart 使用與類名相同的名稱定義建構函式。建構函式是一個函式,因此可以是引數化的。但是,與函式不同,建構函式不能有返回型別。如果您不宣告建構函式,則會為您提供一個預設的無引數建構函式

語法

Class_name(parameter_list) { 
   //constructor body 
}

示例

以下示例演示瞭如何在 Dart 中使用建構函式:

void main() { 
   Car c = new Car('E1001'); 
} 
class Car { 
   Car(String engine) { 
      print(engine); 
   } 
}

它應產生以下輸出

E1001 

命名建構函式

Dart 提供命名建構函式來使類能夠定義多個建構函式。命名建構函式的語法如下所示:

語法:定義建構函式

Class_name.constructor_name(param_list)

示例

以下示例演示瞭如何在 Dart 中使用命名建構函式:

void main() {           
   Car c1 = new Car.namedConst('E1001');                                       
   Car c2 = new Car(); 
}           
class Car {                   
   Car() {                           
      print("Non-parameterized constructor invoked");
   }                                   
   Car.namedConst(String engine) { 
      print("The engine is : ${engine}");    
   }                               
}

它應產生以下輸出

The engine is : E1001 
Non-parameterized constructor invoked

this 關鍵字

this 關鍵字引用類的當前例項。在這裡,引數名稱和類欄位的名稱相同。因此,為了避免歧義,類欄位以this 關鍵字為字首。以下示例說明了這一點:

示例

以下示例說明了如何在 Dart 中使用this 關鍵字:

void main() { 
   Car c1 = new Car('E1001'); 
}  
class Car { 
   String engine; 
   Car(String engine) { 
      this.engine = engine; 
      print("The engine is : ${engine}"); 
   } 
} 

它應產生以下輸出

The engine is : E1001

Dart 類 ─ Getter 和 Setter

GetterSetter,也稱為訪問器修改器,分別允許程式初始化和檢索類欄位的值。Getter 或訪問器使用get 關鍵字定義。Setter 或修改器使用set 關鍵字定義。

每個類都關聯一個預設的 getter/setter。但是,可以透過顯式定義 setter/getter 來覆蓋預設的 getter/setter。getter 沒有引數並返回值,而 setter 有一個引數並且不返回值。

語法:定義 getter

Return_type  get identifier 
{ 
} 

語法:定義 setter

set identifier 
{ 
}

示例

以下示例演示瞭如何在 Dart 類中使用gettersetter

class Student { 
   String name; 
   int age; 
    
   String get stud_name { 
      return name; 
   } 
    
   void set stud_name(String name) { 
      this.name = name; 
   } 
   
   void set stud_age(int age) { 
      if(age<= 0) { 
        print("Age should be greater than 5"); 
      }  else { 
         this.age = age; 
      } 
   } 
   
   int get stud_age { 
      return age;     
   } 
}  
void main() { 
   Student s1 = new Student(); 
   s1.stud_name = 'MARK'; 
   s1.stud_age = 0; 
   print(s1.stud_name); 
   print(s1.stud_age); 
} 

此程式程式碼應產生以下輸出

Age should be greater than 5 
MARK 
Null 

類繼承

Dart 支援繼承的概念,即程式能夠從現有類建立新類。用於擴充套件以建立新類的類稱為父類/超類。新建立的類稱為子類/子類。

一個類使用“extends”關鍵字從另一個類繼承。子類繼承父類中的所有屬性和方法,除了建構函式

語法

class child_class_name extends parent_class_name 

注意 - Dart 不支援多重繼承。

示例:類繼承

在以下示例中,我們聲明瞭一個類ShapeCircle 類擴充套件了該類。由於類之間存在繼承關係,因此子類,即Car 類可以隱式訪問其父類的資料成員。

void main() { 
   var obj = new Circle(); 
   obj.cal_area(); 
}  
class Shape { 
   void cal_area() { 
      print("calling calc area defined in the Shape class"); 
   } 
}  
class Circle extends Shape {}

它應產生以下輸出

calling calc area defined in the Shape class

繼承型別

繼承可以分為以下三種類型:

  • 單一 - 每個類最多可以從一個父類繼承。

  • 多重 - 一個類可以從多個類繼承。Dart 不支援多重繼承。

  • 多級 - 一個類可以從另一個子類繼承。

示例

以下示例演示了多級繼承的工作原理:

void main() { 
   var obj = new Leaf(); 
   obj.str = "hello"; 
   print(obj.str); 
}  
class Root { 
   String str; 
}  
class Child extends Root {}  
class Leaf extends Child {}  
//indirectly inherits from Root by virtue of inheritance

Leaf 類透過多級繼承從 Root 和 Child 類派生屬性。其輸出如下所示:

hello

Dart – 類繼承和方法重寫

方法重寫是一種機制,子類可以透過它重新定義其父類中的方法。以下示例說明了這一點:

示例

void main() { 
   Child c = new Child(); 
   c.m1(12); 
} 
class Parent { 
   void m1(int a){ print("value of a ${a}");} 
}  
class Child extends Parent { 
   @override 
   void m1(int b) { 
      print("value of b ${b}"); 
   } 
}

它應產生以下輸出

value of b 12

重寫方法時,函式引數的數量和型別必須匹配。如果引數數量或其資料型別不匹配,Dart 編譯器將丟擲錯誤。以下插圖說明了這一點:

import 'dart:io'; 
void main() { 
   Child c = new Child(); 
   c.m1(12); 
} 
class Parent { 
   void m1(int a){ print("value of a ${a}");} 
} 
class Child extends Parent { 
   @override 
   void m1(String b) { 
      print("value of b ${b}");
   } 
}

它應產生以下輸出

value of b 12

static 關鍵字

static 關鍵字可以應用於類的成員資料,即欄位方法。靜態變數保留其值,直到程式執行完成。靜態成員由類名引用。

示例

class StaticMem { 
   static int num;  
   static disp() { 
      print("The value of num is ${StaticMem.num}")  ; 
   } 
}  
void main() { 
   StaticMem.num = 12;  
   // initialize the static variable } 
   StaticMem.disp();   
   // invoke the static method 
}

它應產生以下輸出

The value of num is 12

super 關鍵字

super 關鍵字用於引用類的直接父類。該關鍵字可以用於引用變數、屬性方法的超類版本。以下示例說明了這一點:

示例

void main() { 
   Child c = new Child(); 
   c.m1(12); 
} 
class Parent { 
   String msg = "message variable from the parent class"; 
   void m1(int a){ print("value of a ${a}");} 
} 
class Child extends Parent { 
   @override 
   void m1(int b) { 
      print("value of b ${b}"); 
      super.m1(13); 
      print("${super.msg}")   ; 
   } 
}

它應產生以下輸出

value of b 12 
value of a 13 
message variable from the parent class

Dart 程式設計 - 物件

面向物件程式設計將物件定義為“任何具有定義邊界的實體”。物件具有以下特徵:

  • 狀態 - 描述物件。類的欄位表示物件的狀態。

  • 行為 - 描述物件可以做什麼。

  • 標識 - 一個唯一的值,用於區分一組類似的其他物件中的物件。兩個或多個物件可以共享狀態和行為,但不能共享標識。

句點運算子(.) 與物件一起使用以訪問類的資料成員。

示例

Dart 以物件的形式表示資料。Dart 中的每個類都擴充套件了 Object 類。下面是一個建立和使用物件的簡單示例。

class Student { 
   void test_method() { 
      print("This is a  test method"); 
   } 
   
   void test_method1() { 
      print("This is a  test method1"); 
   } 
}  
void main()    { 
   Student s1 = new Student(); 
   s1.test_method(); 
   s1.test_method1(); 
}

它應產生以下輸出

This is a test method 
This is a test method1

級聯運算子 (..)

上面的示例在類中呼叫方法。但是,每次呼叫函式時,都需要引用該物件。級聯運算子可以用作簡寫,在存在一系列呼叫時。

級聯 ( .. ) 運算子可用於透過物件發出一系列呼叫。上面的示例可以改寫如下。

class Student { 
   void test_method() { 
      print("This is a  test method"); 
   } 
   
   void test_method1() { 
      print("This is a  test method1"); 
   } 
}  
void main() { 
   new Student() 
   ..test_method() 
   ..test_method1(); 
}

它應產生以下輸出

This is a test method 
This is a test method1

toString() 方法

此函式返回物件的字串表示形式。請檢視以下示例,瞭解如何使用toString 方法。

void main() { 
   int n = 12; 
   print(n.toString()); 
} 

它應產生以下輸出

12

Dart 程式設計 - 集合

與其他程式語言不同,Dart 不支援陣列。Dart 集合可用於複製諸如陣列之類的的資料結構。dart:core 庫和其他類在 Dart 指令碼中啟用了集合支援。

Dart 集合基本上可以分為:

序號 Dart 集合和描述
1 List

List 只是一個物件的排序組。dart:core 庫提供了 List 類,該類支援列表的建立和操作。

  • 固定長度列表 - 列表的長度在執行時不能更改。

  • 可增長列表 - 列表的長度可以在執行時更改。

2 Set

Set 表示物件的集合,其中每個物件只能出現一次。dart:core 庫提供了 Set 類來實現這一點。

3 對映

Map 物件是一個簡單的鍵/值對。Map 中的鍵和值可以是任何型別。Map 是一個動態集合。換句話說,Map 可以在執行時增長和縮小。dart:core 庫中的 Map 類為此提供了支援。

4 Queue

Queue 是一個可以在兩端進行操作的集合。當您想要構建一個先進先出集合時,佇列很有用。簡單來說,佇列從一端插入資料,從另一端刪除資料。值按插入順序刪除/讀取。

迭代集合

dart:core 庫中的 Iterator 類支援輕鬆遍歷集合。每個集合都有一個iterator 屬性。此屬性返回一個指向集合中物件的迭代器。

示例

以下示例說明了如何使用迭代器物件遍歷集合。

import 'dart:collection'; 
void main() { 
   Queue numQ = new Queue(); 
   numQ.addAll([100,200,300]);  
   Iterator i= numQ.iterator; 
   
   while(i.moveNext()) { 
      print(i.current); 
   } 
}

moveNext() 函式返回一個布林值,指示是否存在後續條目。迭代器物件的current 屬性返回迭代器當前指向的物件的值。

此程式應產生以下輸出

100 
200 
300

Dart 程式設計 - 泛型

Dart 是一種可選型別語言。預設情況下,Dart 中的集合是異構的。換句話說,單個 Dart 集合可以容納各種型別的值。但是,可以使 Dart 集合儲存同構值。泛型概念可以用來實現這一點。

泛型的使用對集合中可以包含的值的資料型別施加了限制。此類集合被稱為型別安全的集合。型別安全是一種程式設計特性,它確保記憶體塊只能包含特定資料型別的資料。

所有 Dart 集合都透過泛型支援型別安全實現。一對包含資料型別的尖括號用於宣告型別安全的集合。宣告型別安全集合的語法如下所示。

語法

Collection_name <data_type> identifier= new Collection_name<data_type> 

下面給出了 List、Map、Set 和 Queue 的型別安全實現。此功能也受上述所有集合型別的所有實現支援。

示例:泛型 List

void main() { 
   List <String> logTypes = new List <String>(); 
   logTypes.add("WARNING"); 
   logTypes.add("ERROR"); 
   logTypes.add("INFO");  
   
   // iterating across list 
   for (String type in logTypes) { 
      print(type); 
   } 
}

它應產生以下輸出

WARNING 
ERROR 
INFO

嘗試插入除指定型別以外的值將導致編譯錯誤。以下示例說明了這一點。

示例

void main() { 
   List <String> logTypes = new List <String>(); 
   logTypes.add(1); 
   logTypes.add("ERROR"); 
   logTypes.add("INFO"); 
  
   //iterating across list 
   for (String type in logTypes) { 
      print(type); 
   } 
} 

它應產生以下輸出

1                                                                                     
ERROR                                                                             
INFO

示例:泛型 Set

void main() { 
   Set <int>numberSet = new  Set<int>(); 
   numberSet.add(100); 
   numberSet.add(20); 
   numberSet.add(5); 
   numberSet.add(60);
   numberSet.add(70); 
   
   // numberSet.add("Tom"); 
   compilation error; 
   print("Default implementation  :${numberSet.runtimeType}");  
   
   for(var no in numberSet) { 
      print(no); 
   } 
} 

它應產生以下輸出

Default implementation :_CompactLinkedHashSet<int> 
100 
20 
5 
60 
70

示例:泛型 Queue

import 'dart:collection'; 
void main() { 
   Queue<int> queue = new Queue<int>(); 
   print("Default implementation ${queue.runtimeType}");  
   queue.addLast(10); 
   queue.addLast(20); 
   queue.addLast(30); 
   queue.addLast(40); 
   queue.removeFirst();  
   
   for(int no in queue){ 
      print(no); 
   } 
}

它應產生以下輸出

Default implementation ListQueue<int> 
20 
30 
40

泛型 Map

型別安全的對映宣告指定了以下資料型別:

語法

Map <Key_type, value_type>

示例

void main() { 
   Map <String,String>m={'name':'Tom','Id':'E1001'}; 
   print('Map :${m}'); 
} 

它應產生以下輸出

Map :{name: Tom, Id: E1001}

Dart 程式設計 - 包

包是一種封裝一組程式設計單元的機制。應用程式有時可能需要整合一些第三方庫或外掛。每種語言都有一個管理外部包的機制,例如 Java 的 Maven 或 Gradle、.NET 的 Nuget、Node.js 的 npm 等。Dart 的包管理器是pub

Pub 幫助在儲存庫中安裝包。託管的包儲存庫可以在 https://pub.dartlang.org/ 找到。

包元資料在檔案pubspec.yaml中定義。YAML 是Yet Another Markup Language的首字母縮寫詞。pub工具可用於下載應用程式所需的所有各種庫。

每個 Dart 應用程式都有一個pubspec.yaml檔案,其中包含應用程式對其他庫的依賴項以及應用程式的元資料,例如應用程式名稱、作者、版本和描述。

pubspec.yaml檔案的內容應如下所示:

name: 'vector_victor' 
version: 0.0.1 
description: An absolute bare-bones web app. 
... 
dependencies: browser: '>=0.10.0 <0.11.0' 

重要的pub 命令如下:

序號 命令 & 描述
1

‘pub get’

幫助獲取應用程式依賴的所有包。

2

‘pub upgrade’

將所有依賴項升級到較新版本。

3

‘pub build’

這用於構建 Web 應用程式,它將建立一個 build 資料夾,其中包含所有相關的指令碼。

4

‘pub help’

這將為您提供所有不同 pub 命令的幫助。

如果您使用的是 WebStorm 等 IDE,則可以右鍵單擊 pubspec.yaml 以直接獲取所有命令:

Pubspec.yaml

安裝包

考慮一個應用程式需要解析 xml 的示例。Dart XML 是一個輕量級庫,它是開源且穩定的,用於解析、遍歷、查詢和構建 XML 文件。

實現上述任務的步驟如下:

步驟 1 - 將以下內容新增到 pubspec.yaml 檔案中。

name: TestApp 
version: 0.0.1 
description: A simple console application. 
#dependencies: 
#  foo_bar: '>=1.0.0 <2.0.0' 
dependencies: https://mail.google.com/mail/u/0/images/cleardot.gif
xml: 

右鍵單擊pubspec.yaml並獲取依賴項。這將在內部觸發pub get 命令,如下所示。

Pub Get Command

下載的包及其依賴包可以在 packages 資料夾下進行驗證。

Packages

由於安裝已完成,現在我們需要在專案中引用dart xml。語法如下:

import 'package:xml/xml.dart' as xml;

讀取 XML 字串

要讀取 XML 字串並驗證輸入,Dart XML 使用parse()方法。語法如下:

xml.parse(String input):

示例:解析 XML 字串輸入

以下示例顯示瞭如何解析 XML 字串輸入:

import 'package:xml/xml.dart' as xml; 
void main(){ 
   print("xml"); 
   var bookshelfXml = '''<?xml version = "1.0"?> 
   <bookshelf> 
      <book> 
         <title lang = "english">Growing a Language</title> 
         <price>29.99</price> 
      </book> 
      
      <book> 
         <title lang = "english">Learning XML</title> 
         <price>39.95</price> 
      </book> 
      <price>132.00</price> 
   </bookshelf>'''; 
   
   var document = xml.parse(bookshelfXml); 
   print(document.toString()); 
}

它應產生以下輸出

xml 
<?xml version = "1.0"?><bookshelf> 
   <book> 
      <title lang = "english">Growing a Language</title> 
      <price>29.99</price> 
   </book> 

   <book> 
      <title lang = "english">Learning XML</title> 
      <price>39.95</price> 
   </book> 
   <price>132.00</price> 
</bookshelf> 

Dart 程式設計 - 異常

異常(或異常事件)是在程式執行期間出現的問題。當發生異常時,程式的正常流程被打斷,程式/應用程式異常終止。

內建的 Dart 異常包括:

序號 異常 & 描述
1

DeferredLoadException

當延遲載入的庫載入失敗時丟擲。

2

FormatException

當字串或其他一些資料沒有預期的格式並且無法解析或處理時丟擲的異常。

3

IntegerDivisionByZeroException

當一個數字除以零時丟擲。

4

IOException

所有輸入輸出相關異常的基類。

5

IsolateSpawnException

當無法建立隔離區時丟擲。

6

Timeout

當等待非同步結果時發生計劃的超時時丟擲。

Dart 中的每個異常都是預定義類Exception的子型別。必須處理異常以防止應用程式突然終止。

try / on / catch 塊

try塊嵌入可能導致異常的程式碼。當需要指定異常型別時使用 on 塊。當處理程式需要異常物件時使用catch塊。

try塊後面必須緊跟一個on / catch塊或一個finally塊(或兩者之一)。當 try 塊中發生異常時,控制權將轉移到catch

處理異常的語法如下所示:

try { 
   // code that might throw an exception 
}  
on Exception1 { 
   // code for handling exception 
}  
catch Exception2 { 
   // code for handling exception 
} 

以下是一些需要記住的要點:

  • 程式碼片段可以有多個 on / catch 塊來處理多個異常。

  • on 塊和 catch 塊是互斥的,即 try 塊可以同時與 on 塊和 catch 塊關聯。

以下程式碼說明了 Dart 中的異常處理:

示例:使用 ON 塊

以下程式除以變數xy分別表示的兩個數字。程式碼丟擲異常,因為它嘗試除以零。on 塊包含處理此異常的程式碼。

main() { 
   int x = 12; 
   int y = 0; 
   int res;  
   
   try {
      res = x ~/ y; 
   } 
   on IntegerDivisionByZeroException { 
      print('Cannot divide by zero'); 
   } 
} 

它應產生以下輸出

Cannot divide by zero

示例:使用 catch 塊

在以下示例中,我們使用了與上面相同的程式碼。唯一的區別是catch 塊(而不是 ON 塊)此處包含處理異常的程式碼。catch的引數包含在執行時丟擲的異常物件。

main() { 
   int x = 12; 
   int y = 0; 
   int res;  
   
   try {  
      res = x ~/ y; 
   }  
   catch(e) { 
      print(e); 
   } 
} 

它應產生以下輸出

IntegerDivisionByZeroException

示例:on…catch

以下示例顯示瞭如何使用on...catch塊。

main() { 
   int x = 12; 
   int y = 0; 
   int res;  
   
   try { 
      res = x ~/ y; 
   }  
   on IntegerDivisionByZeroException catch(e) { 
      print(e); 
   } 
} 

它應產生以下輸出

IntegerDivisionByZeroException

Finally 塊

finally塊包含無論異常是否發生都應執行的程式碼。可選的finally塊在try/on/catch之後無條件執行。

使用finally塊的語法如下:

try { 
   // code that might throw an exception 
}  
on Exception1 { 
   // exception handling code 
}  
catch Exception2 { 
   //  exception handling 
}  
finally { 
   // code that should always execute; irrespective of the exception 
}

以下示例說明了finally塊的使用。

main() { 
   int x = 12; 
   int y = 0; 
   int res;  
   
   try { 
      res = x ~/ y; 
   } 
   on IntegerDivisionByZeroException { 
      print('Cannot divide by zero'); 
   } 
   finally { 
      print('Finally block executed'); 
   } 
}

它應產生以下輸出

Cannot divide by zero 
Finally block executed

丟擲異常

throw關鍵字用於顯式引發異常。應處理引發的異常以防止程式突然退出。

顯式引發異常的語法為:

throw new Exception_name()

示例

以下示例顯示瞭如何使用throw關鍵字丟擲異常:

main() { 
   try { 
      test_age(-2); 
   } 
   catch(e) { 
      print('Age cannot be negative'); 
   } 
}  
void test_age(int age) { 
   if(age<0) { 
      throw new FormatException(); 
   } 
}

它應產生以下輸出

Age cannot be negative

自定義異常

如上所述,Dart 中的每個異常型別都是內建類Exception的子型別。Dart 透過擴充套件現有異常來建立自定義異常。定義自定義異常的語法如下所示:

語法:定義異常

class Custom_exception_Name implements Exception { 
   // can contain constructors, variables and methods 
} 

自定義異常應顯式引發,並且應在程式碼中進行處理。

示例

以下示例顯示瞭如何定義和處理自定義異常。

class AmtException implements Exception { 
   String errMsg() => 'Amount should be greater than zero'; 
}  
void main() { 
   try { 
      withdraw_amt(-1); 
   } 
   catch(e) { 
      print(e.errMsg()); 
   }  
finally { 
      print('Ending requested operation.....'); 
   } 
}  
void withdraw_amt(int amt) { 
   if (amt <= 0) { 
      throw new AmtException(); 
   } 
}  

在上面的程式碼中,我們正在定義一個自定義異常AmtException。如果傳遞的金額不在預期範圍內,程式碼將引發異常。main函式將函式呼叫包含在try...catch塊中。

程式碼應產生以下輸出 -

Amount should be greater than zero 
Ending requested operation.... 

Dart 程式設計 - 除錯

開發人員在編碼時會不時地犯錯誤。程式中的錯誤稱為 bug。查詢和修復 bug 的過程稱為除錯,是開發過程的正常部分。本節介紹可以幫助您完成除錯任務的工具和技術。

WebStorm 編輯器支援斷點和逐步除錯。程式將在附加斷點的位置中斷。此功能類似於您可能從 Java 或 C# 應用程式開發中獲得的功能。您可以觀察變數、瀏覽堆疊、單步執行和進入方法和函式呼叫,所有這些都來自 WebStorm 編輯器。

新增斷點

考慮以下程式碼片段。(TestString.dart)

void main() { 
   int a = 10, b = 20, c = 5; 
   c = c * c * c; 
   
   print("$a + $b = ${a+b}"); 
   print("$a%$b = ${a%b}");  // Add a break point here 
   print("$a*$b = ${a*b}"); 
   print("$a/$b = ${a/b}"); 
   print(c); 
}

新增斷點,請單擊左側邊距。在下圖中,第 7 行有一個斷點。

Add a Breakpoint

在除錯模式下執行程式。在專案資源管理器中,右鍵單擊 Dart 程式,在本例中為 TestString.dart。

Debug TestString

程式在除錯模式下執行後,您將獲得如下所示的偵錯程式視窗。變數選項卡顯示當前上下文中變數的值。您可以為特定變數新增觀察器,並使用觀察器視窗監聽這些值的更改。

Add Watchers

Step Into(F7)除錯選單上的箭頭圖示有助於逐語句執行程式碼。如果主方法呼叫子例程,則這也將進入子例程程式碼。

Step Over(F8):它類似於Step Into。使用上的差異發生在當前語句包含對子例程的呼叫時。如果主方法呼叫子例程,則 Step Over 不會深入子例程。它將跳過子例程。

Step Out(Shift+F8):執行當前執行點所在的函式的其餘行。顯示的下一條語句是子例程呼叫後的語句。

在除錯模式下執行後,程式給出以下輸出

10 + 20 = 30 
10 % 20 = 10 
10 * 20 = 200 
10 / 20 = 0.5 
125

Dart 程式設計 - 型別定義

typedef或函式類型別名有助於定義指向記憶體中可執行程式碼的指標。簡單來說,typedef可以作為引用函式的指標使用。

以下是 Dart 程式中實現typedef的步驟。

步驟 1:定義 typedef

typedef可用於指定我們希望特定函式匹配的函式簽名。函式簽名由函式的引數(包括其型別)定義。返回型別不是函式簽名的一部分。其語法如下。

typedef function_name(parameters)

步驟 2:將函式分配給 typedef 變數

typedef的變數可以指向任何具有與typedef相同簽名的函式。您可以使用以下簽名將函式分配給typedef變數。

type_def  var_name = function_name

步驟 3:呼叫函式

typedef變數可用於呼叫函式。以下是如何呼叫函式:

var_name(parameters) 

示例

現在讓我們舉一個例子來了解 Dart 中的typedef

首先,讓我們定義一個typedef。在這裡,我們正在定義一個函式簽名。該函式將接收兩個型別為integer的輸入引數。返回型別不是函式簽名的一部分。

typedef ManyOperation(int firstNo , int secondNo); //function signature

接下來,讓我們定義函式。定義一些與ManyOperation typedef具有相同函式簽名的函式。

Add(int firstNo,int second){ 
   print("Add result is ${firstNo+second}"); 
}  
Subtract(int firstNo,int second){ 
   print("Subtract result is ${firstNo-second}"); 
}  
Divide(int firstNo,int second){ 
   print("Add result is ${firstNo/second}"); 
}

最後,我們將透過typedef呼叫函式。宣告一個 ManyOperations 型別的變數。將函式名稱分配給宣告的變數。

ManyOperation oper ;  

//can point to any method of same signature 
oper = Add; 
oper(10,20); 
oper = Subtract; 
oper(30,20); 
oper = Divide; 
oper(50,5); 

oper變數可以指向任何接收兩個整數引數的方法。Add函式的引用被分配給該變數。Typedef可以在執行時切換函式引用

現在讓我們將所有部分放在一起,看看完整的程式。

typedef ManyOperation(int firstNo , int secondNo); 
//function signature  

Add(int firstNo,int second){ 
   print("Add result is ${firstNo+second}"); 
} 
Subtract(int firstNo,int second){ 
   print("Subtract result is ${firstNo-second}"); 
}
Divide(int firstNo,int second){ 
   print("Divide result is ${firstNo/second}"); 
}  
Calculator(int a, int b, ManyOperation oper){ 
   print("Inside calculator"); 
   oper(a,b); 
}  
void main(){ 
   ManyOperation oper = Add; 
   oper(10,20); 
   oper = Subtract; 
   oper(30,20); 
   oper = Divide; 
   oper(50,5); 
} 

程式應產生以下輸出

Add result is 30 
Subtract result is 10 
Divide result is 10.0 

注意 - 如果typedef變數試圖指向具有不同函式簽名的函式,則上述程式碼將導致錯誤。

示例

Typedef也可以作為引數傳遞給函式。考慮以下示例:

typedef ManyOperation(int firstNo , int secondNo);   //function signature 
Add(int firstNo,int second){ 
   print("Add result is ${firstNo+second}"); 
}  
Subtract(int firstNo,int second){
   print("Subtract result is ${firstNo-second}"); 
}  
Divide(int firstNo,int second){ 
   print("Divide result is ${firstNo/second}"); 
}  
Calculator(int a,int b ,ManyOperation oper){ 
   print("Inside calculator"); 
   oper(a,b); 
}  
main(){ 
   Calculator(5,5,Add); 
   Calculator(5,5,Subtract); 
   Calculator(5,5,Divide); 
} 

它將產生以下輸出 -

Inside calculator 
Add result is 10 
Inside calculator 
Subtract result is 0 
Inside calculator 
Divide result is 1.0

Dart 程式設計 - 庫

程式語言中的庫表示一系列例程(一組程式設計指令)。Dart 有一組內建庫,這些庫對於儲存經常使用的例程很有用。Dart 庫包含一組類、常量、函式、typedef、屬性和異常。

匯入庫

匯入使庫中的元件可用於呼叫方程式碼。import 關鍵字用於實現相同的目的。一個 dart 檔案可以有多個 import 語句。

內建的 Dart 庫 URI 使用 dart: 方案來引用庫。其他庫可以使用檔案系統路徑或 package: 方案來指定其 URI。由包管理器(例如 pub 工具)提供的庫使用package: 方案

在 Dart 中匯入庫的語法如下所示:

import 'URI'

考慮以下程式碼片段:

import 'dart:io' 
import 'package:lib1/libfile.dart' 

如果只想使用庫的一部分,可以選擇性地匯入該庫。相應的語法如下所示:

import 'package: lib1/lib1.dart' show foo, bar;  
// Import only foo and bar. 

import 'package: mylib/mylib.dart' hide foo;  
// Import all names except foo

以下是一些常用的庫:

序號 庫 & 描述
1

dart:io

用於伺服器應用程式的檔案、套接字、HTTP 和其他 I/O 支援。此庫不適用於基於瀏覽器的應用程式。此庫預設匯入。

2

dart:core

每個 Dart 程式的內建型別、集合和其他核心功能。此庫會自動匯入。

3

dart:math

數學常數和函式,以及隨機數生成器。

4

dart:convert

用於在不同資料表示形式(包括 JSON 和 UTF-8)之間轉換的編碼器和解碼器。

5

dart:typed_data

有效處理固定大小資料的列表(例如,無符號 8 位元組整數)。

示例:匯入和使用庫

以下示例匯入內建庫dart:math。該程式碼片段呼叫math庫中的sqrt()函式。此函式返回傳遞給它的數字的平方根。

import 'dart:math'; 
void main() { 
   print("Square root of 36 is: ${sqrt(36)}"); 
}

輸出

Square root of 36 is: 6.0

庫中的封裝

Dart 指令碼可以使用下劃線 ( _ ) 為識別符號新增字首,以將其元件標記為私有。簡單來說,Dart 庫可以透過限制外部指令碼訪問其內容來限制訪問。這稱為封裝。相應的語法如下所示:

語法

_identifier

示例

首先,定義一個包含私有函式的庫。

library loggerlib;                            
void _log(msg) {
   print("Log method called in loggerlib msg:$msg");      
} 

接下來,匯入庫

import 'test.dart' as web; 
void main() { 
   web._log("hello from webloggerlib"); 
} 

以上程式碼將導致錯誤。

Unhandled exception: 
No top-level method 'web._log' declared.  
NoSuchMethodError: method not found: 'web._log' 
Receiver: top-level 
Arguments: [...] 
#0 NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:184) 
#1 main (file:///C:/Users/Administrator/WebstormProjects/untitled/Assertion.dart:6:3) 
#2 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:261) 
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

建立自定義庫

Dart 還允許您使用自己的程式碼作為庫。建立自定義庫涉及以下步驟:

步驟 1:宣告庫

要顯式宣告庫,請使用library 語句。宣告庫的語法如下所示:

library library_name  
// library contents go here 

步驟 2:關聯庫

您可以透過兩種方式關聯庫:

  • 在同一目錄中
import 'library_name'
  • 從不同的目錄
import 'dir/library_name'

示例:自定義庫

首先,讓我們定義一個自定義庫calculator.dart

library calculator_lib;  
import 'dart:math'; 

//import statement after the libaray statement  
int add(int firstNumber,int secondNumber){ 
   print("inside add method of Calculator Library ") ; 
   return firstNumber+secondNumber; 
}  
int modulus(int firstNumber,int secondNumber){ 
   print("inside modulus method of Calculator Library ") ; 
   return firstNumber%secondNumber; 
}  
int random(int no){ 
   return new Random().nextInt(no); 
}

接下來,我們將匯入庫:

import 'calculator.dart';  
void main() {
   var num1 = 10; 
   var num2 = 20; 
   var sum = add(num1,num2); 
   var mod = modulus(num1,num2); 
   var r = random(10);  
   
   print("$num1 + $num2 = $sum"); 
   print("$num1 % $num2= $mod"); 
   print("random no $r"); 
} 

程式應產生以下輸出

inside add method of Calculator Library  
inside modulus method of Calculator Library  
10 + 20 = 30 
10 % 20= 10 
random no 0 

庫字首

如果匯入兩個具有衝突識別符號的庫,則可以為一個或兩個庫指定字首。使用'as'關鍵字指定字首。相應的語法如下所示:

語法

import 'library_uri' as prefix

示例

首先,讓我們定義一個庫:loggerlib.dart

library loggerlib;  
void log(msg){ 
   print("Log method called in loggerlib msg:$msg");
}   

接下來,我們將定義另一個庫:webloggerlib.dart

library webloggerlib; 
void log(msg){ 
   print("Log method called in webloggerlib msg:$msg"); 
} 

最後,我們將使用字首匯入庫。

import 'loggerlib.dart'; 
import 'webloggerlib.dart' as web;  

// prefix avoids function name clashes 
void main(){ 
   log("hello from loggerlib"); 
   web.log("hello from webloggerlib"); 
} 

它將產生以下輸出 -

Log method called in loggerlib msg:hello from loggerlib 
Log method called in webloggerlib msg:hello from webloggerlib 

Dart 程式設計 - 非同步

非同步操作在一個執行緒中執行,與應用程式執行緒分離。當應用程式呼叫方法非同步執行操作時,應用程式可以繼續執行,而非同步方法執行其任務。

示例

讓我們舉一個例子來理解這個概念。在這裡,程式使用IO 庫接受使用者輸入。

import 'dart:io'; 
void main() { 
   print("Enter your name :");            
   
   // prompt for user input 
   String name = stdin.readLineSync();  
   
   // this is a synchronous method that reads user input 
   print("Hello Mr. ${name}"); 
   print("End of main"); 
} 

readLineSync()是一個同步方法。這意味著,在readLineSync()函式呼叫之後的所有指令的執行將被阻塞,直到readLineSync()方法完成執行。

stdin.readLineSync等待輸入。它會停止執行並不會繼續執行任何操作,直到它收到使用者的輸入。

以上示例將產生以下輸出

Enter your name :     
Tom                   

// reads user input  
Hello Mr. Tom 
End of main

在計算中,當某個操作在繼續執行之前等待事件發生時,我們稱之為同步。這種方法的一個缺點是,如果程式碼的一部分執行時間過長,則後續的程式碼塊,即使不相關,也會被阻止執行。考慮一個必須響應多個資源請求的 Web 伺服器。

同步執行模型將阻塞所有其他使用者的請求,直到它完成當前請求的處理。在這種情況下,例如 Web 伺服器,每個請求都必須獨立於其他請求。這意味著,Web 伺服器不應該等待當前請求完成執行,然後再響應其他使用者的請求。

簡單來說,它應該在完成先前使用者的請求之前接受新使用者的請求。這稱為非同步。非同步程式設計基本上意味著沒有等待或非阻塞程式設計模型。dart:async包有助於在 Dart 指令碼中實現非同步程式設計塊。

示例

以下示例更好地說明了非同步塊的功能。

步驟 1 - 建立一個contact.txt檔案,如下所示將其儲存在當前專案中的 data 資料夾中。

1, Tom 
2, John 
3, Tim 
4, Jane 

步驟 2 - 編寫一個程式,在不阻塞應用程式其他部分的情況下讀取檔案。

import "dart:async"; 
import "dart:io";  

void main(){ 
   File file = new File( Directory.current.path+"\\data\\contact.txt"); 
   Future<String> f = file.readAsString();  
  
   // returns a futrue, this is Async method 
   f.then((data)=>print(data));  
   
   // once file is read , call back method is invoked  
   print("End of main");  
   // this get printed first, showing fileReading is non blocking or async 
}

此程式的輸出如下所示:

End of main 
1, Tom 
2, John 
3, Tim 
4, Jan

"end of main" 首先執行,而指令碼繼續讀取檔案。Future類(dart:async的一部分)用於在非同步任務完成後獲取計算結果。然後使用此Future值在計算完成後執行某些操作。

讀取操作完成後,執行控制權將轉移到"then()"內。這是因為讀取操作可能需要更多時間,因此它不想阻塞程式的其他部分。

Dart Future

Dart 社群將Future定義為“一種在將來某個時間獲取值的方法”。簡單來說,Future 物件是一種表示由表示式返回的值的機制,該表示式的執行將在以後的某個時間點完成。Dart 的許多內建類在呼叫非同步方法時都會返回Future

Dart 是一種單執行緒程式語言。如果任何程式碼阻塞執行執行緒(例如,透過等待耗時操作或阻塞 I/O),則程式實際上會凍結。

非同步操作允許您的程式在不發生阻塞的情況下執行。Dart 使用Future 物件來表示非同步操作。

Dart 程式設計 - 併發

併發是同時執行多個指令序列。它涉及同時執行多個任務。

Dart 使用Isolate作為並行執行工作的工具。dart:isolate包是 Dart 的解決方案,用於獲取單執行緒 Dart 程式碼並允許應用程式更好地利用可用的硬體。

Isolate顧名思義,是執行程式碼的隔離單元。它們之間傳遞資料的唯一方法是透過傳遞訊息,就像您在客戶端和伺服器之間傳遞訊息的方式一樣。Isolate幫助程式利用多核微處理器。

示例

讓我們舉一個例子來更好地理解這個概念。

import 'dart:isolate';  
void foo(var message){ 
   print('execution from foo ... the message is :${message}'); 
}  
void main(){ 
   Isolate.spawn(foo,'Hello!!'); 
   Isolate.spawn(foo,'Greetings!!'); 
   Isolate.spawn(foo,'Welcome!!'); 
   
   print('execution from main1'); 
   print('execution from main2'); 
   print('execution from main3'); 
}

在這裡,Isolate類的spawn方法有助於與程式碼的其餘部分並行執行函式foospawn函式接受兩個引數:

  • 要生成的函式,以及
  • 將傳遞給生成的函式的物件。

如果沒有要傳遞給生成的函式的物件,可以傳遞 NULL 值。

這兩個函式(foo 和 main)不一定每次都按相同的順序執行。無法保證foo何時執行以及main()何時執行。每次執行時輸出將不同。

輸出 1

execution from main1 
execution from main2 
execution from main3 
execution from foo ... the message is :Hello!! 

輸出 2

execution from main1 
execution from main2 
execution from main3 
execution from foo ... the message is :Welcome!! 
execution from foo ... the message is :Hello!! 
execution from foo ... the message is :Greetings!! 

從輸出中,我們可以得出結論,Dart 程式碼可以從正在執行的程式碼中生成新的Isolate,就像 Java 或 C# 程式碼可以啟動新執行緒一樣。

Isolate與執行緒的不同之處在於,Isolate具有自己的記憶體。無法在Isolate之間共享變數——Isolate之間通訊的唯一方法是透過訊息傳遞。

注意 - 對於不同的硬體和作業系統配置,以上輸出將有所不同。

Isolate 與 Future

非同步執行復雜的計算工作對於確保應用程式的響應性非常重要。Dart Future是一種在非同步任務完成後檢索其值的機制,而Dart Isolate是一種用於抽象化並行性和在實踐中以高級別實現它的工具。

Dart 程式設計 - 單元測試

單元測試涉及測試應用程式的每個單獨單元。它幫助開發人員測試小功能,而無需執行整個複雜的應用程式。

名為“test”的 Dart外部庫提供了一種編寫和執行單元測試的標準方法。

Dart 單元測試涉及以下步驟:

步驟 1:安裝“test”包

要在當前專案中安裝第三方包,您需要pubspec.yaml檔案。要安裝test 包,請首先在pubspec.yaml檔案中進行以下條目:

dependencies: 
test:

進行條目後,右鍵單擊pubspec.yaml檔案並獲取依賴項。它將安裝“test”包。以下是WebStorm編輯器中相同的螢幕截圖。

Unit Testing

也可以從命令列安裝包。在終端中鍵入以下內容:

pub get

步驟 2:匯入“test”包

import "package:test/test.dart";

步驟 3 編寫測試

測試使用頂級函式test()指定,而測試斷言使用expect()函式進行。要使用這些方法,應將其安裝為pub依賴項。

語法

test("Description of the test ", () {  
   expect(actualValue , matchingValue) 
});

group()函式可用於對測試進行分組。每個組的描述都會新增到其測試描述的開頭。

語法

group("some_Group_Name", () { 
   test("test_name_1", () { 
      expect(actual, equals(exptected)); 
   });  
   test("test_name_2", () { 
      expect(actual, equals(expected)); 
   }); 
}) 

示例 1:透過測試

以下示例定義了一個方法Add()。此方法接受兩個整數值並返回一個表示的整數。要測試此add()方法:

步驟 1 - 如下所示匯入test包。

步驟 2 - 使用test()函式定義測試。在這裡,test()函式使用expect()函式強制執行斷言。

import 'package:test/test.dart';      
// Import the test package 

int Add(int x,int y)                  
// Function to be tested { 
   return x+y; 
}  
void main() { 
   // Define the test 
   test("test to check add method",(){  
      // Arrange 
      var expected = 30; 
      
      // Act 
      var actual = Add(10,20); 
      
      // Asset 
      expect(actual,expected); 
   }); 
}

它應產生以下輸出

00:00 +0: test to check add method 
00:00 +1: All tests passed! 

示例 2:失敗測試

下面定義的subtract()方法存在邏輯錯誤。以下測試驗證了這一點。

import 'package:test/test.dart'; 
int Add(int x,int y){ 
   return x+y; 
}
int Sub(int x,int y){ 
   return x-y-1; 
}  
void main(){ 
   test('test to check sub',(){ 
      var expected = 10;   
      // Arrange 
      
      var actual = Sub(30,20);  
      // Act 
      
      expect(actual,expected);  
      // Assert 
   }); 
   test("test to check add method",(){ 
      var expected = 30;   
      // Arrange 
      
      var actual = Add(10,20);  
      // Act 
      
      expect(actual,expected);  
      // Asset 
   }); 
}

輸出 - 函式add()的測試用例透過,但subtract()的測試失敗,如下所示。

00:00 +0: test to check sub 
00:00 +0 -1: test to check sub 
Expected: <10> 
Actual: <9> 
package:test  expect 
bin\Test123.dart 18:5  main.<fn> 
   
00:00 +0 -1: test to check add method 
00:00 +1 -1: Some tests failed.  
Unhandled exception: 
Dummy exception to set exit code. 
#0  _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:938) 
#1  _microtaskLoop (dart:async/schedule_microtask.dart:41)
#2  _startMicrotaskLoop (dart:async/schedule_microtask.dart:50) 
#3  _Timer._runTimers (dart:isolate-patch/timer_impl.dart:394) 
#4  _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:414) 
#5  _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148) 

分組測試用例

您可以對測試用例進行分組,以便為您的測試程式碼新增更多含義。如果您有許多測試用例,這有助於編寫更簡潔的程式碼。

在給定的程式碼中,我們正在為split()函式和trim函式編寫測試用例。因此,我們從邏輯上對這些測試用例進行分組並將其稱為String

示例

import "package:test/test.dart"; 
void main() { 
   group("String", () { 
      test("test on split() method of string class", () { 
         var string = "foo,bar,baz"; 
         expect(string.split(","), equals(["foo", "bar", "baz"])); 
      }); 
      test("test on trim() method of string class", () { 
         var string = "  foo "; 
         expect(string.trim(), equals("foo")); 
      }); 
   }); 
} 

輸出 - 輸出將為每個測試用例追加組名稱,如下所示:

00:00 +0: String test on split() method of string class 
00:00 +1: String test on trim() method of string class 
00:00 +2: All tests passed

Dart 程式設計 - HTML DOM

每個網頁都位於可以視為物件的瀏覽器視窗內。

Document 物件表示在該視窗中顯示的 HTML 文件。Document 物件具有各種屬性,這些屬性引用其他物件,允許訪問和修改文件內容。

訪問和修改文件內容的方式稱為**文件物件模型**,或**DOM**。物件以層次結構組織。這種層次結構適用於Web文件中物件的組織。

  • **Window** − 層次結構的頂層。它是物件層次結構的最外層元素。

  • **Document** − 每個載入到視窗中的HTML文件都成為一個文件物件。文件包含頁面的內容。

  • **Elements** − 表示網頁上的內容。例如文字框、頁面標題等。

  • **Nodes** − 通常是元素,但也可以是屬性、文字、註釋和其他DOM型別。

以下是一些重要DOM物件的簡單層次結構:

HTML DOM

Dart提供**dart:html**庫來操作DOM中的物件和元素。基於控制檯的應用程式無法使用**dart:html**庫。要在Web應用程式中使用HTML庫,請匯入**dart:html**:

import 'dart:html';

接下來,我們將在下一節中討論一些**DOM操作**。

查詢DOM元素

**dart:html**庫提供**querySelector**函式來搜尋DOM中的元素。

Element querySelector(String selectors);

**querySelector()**函式返回與指定選擇器組匹配的第一個元素。**"selectors"**應使用如下所示的CSS選擇器語法表示字串

var element1 = document.querySelector('.className'); 
var element2 = document.querySelector('#id'); 

示例:操作DOM

在Webstorm IDE中按照以下步驟操作:

**步驟1** − 檔案->新建專案→在位置處,將專案名稱指定為**DemoWebApp**。

Demowebapp

**步驟2** − 在“生成示例內容”部分,選擇**SimpleWebApplication**。

Create

它將建立一個示例專案**DemoWebApp**。有一個**pubspec.yaml**檔案包含需要下載的依賴項。

name: 'DemoWebApp' 
version: 0.0.1 
description: An absolute bare-bones web app. 

#author: Your Name <email@example.com> 
#homepage: https://www.example.com  
environment:   
   sdk: '>=1.0.0 <2.0.0'  
dependencies:   
   browser: '>=0.10.0 <0.11.0'   dart_to_js_script_rewriter: '^1.0.1'  
transformers: 
- dart_to_js_script_rewriter 

如果您已連線到網路,則這些檔案將自動下載,否則您可以右鍵單擊**pubspec.yaml**並獲取依賴項。

Pub Get Dependencies

在web資料夾中,您將找到三個檔案:**Index.html、main.dart**和**style.css**

Index.html

<!DOCTYPE html>   
<html> 
   <head>     
      <meta charset = "utf-8">     
      <meta http-equiv = "X-UA-Compatible" content = "IE = edge">     
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
      <meta name = "scaffolded-by" content = "https://github.com/google/stagehand">
      <title>DemoWebApp</title>     
      <link rel = "stylesheet" href = "styles.css">     
      <script defer src = "main.dart" type = "application/dart"></script>
      <script defer src = "packages/browser/dart.js"></script> 
   </head>
   
   <body>   
      <h1>
         <div id = "output"></div> 
      </h1>  
   </body> 
</html> 

Main.dart

import 'dart:html';  
void main() {   
   querySelector('#output').text = 'Your Dart web dom app is running!!!.'; 
} 

執行**index.html**檔案;您將在螢幕上看到以下輸出。

Demo Web App

事件處理

**dart:html**庫為DOM元素提供了**onClick**事件。語法顯示了元素如何處理點選事件流。

querySelector('#Id').onClick.listen(eventHanlderFunction); 

**querySelector()**函式從給定的DOM中返回元素,而**onClick.listen()**將獲取一個**eventHandler**方法,該方法將在觸發點選事件時被呼叫。**eventHandler**的語法如下所示:

void eventHanlderFunction (MouseEvent event){ } 

現在讓我們舉一個例子來理解Dart中事件處理的概念。

TestEvent.html

<!DOCTYPE html> 
<html> 
   <head> 
      <meta charset = "utf-8"> 
      <meta http-equiv = "X-UA-Compatible" content = "IE = edge"> 
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0"> 
      <meta name = "scaffolded-by" content ="https://github.com/google/stagehand"> 
      <title>DemoWebApp</title> 
      <link rel = "stylesheet" href = "styles.css"> 
      <script defer src = "TestEvent.dart" type="application/dart"></script> 
      <script defer src = "packages/browser/dart.js"></script> 
   </head> 
   
   <body> 
      <div id = "output"></div> 
      <h1> 
         <div> 
            Enter you name : <input type = "text" id = "txtName"> 
            <input type = "button" id = "btnWish" value="Wish"> 
         </div> 
      </h1> 
      <h2 id = "display"></h2> 
   </body>
   
</html>

TestEvent.dart

import 'dart:html'; 
void main() { 
   querySelector('#btnWish').onClick.listen(wishHandler); 
}  
void wishHandler(MouseEvent event){ 
   String name = (querySelector('#txtName')  as InputElement).value; 
   querySelector('#display').text = 'Hello Mr.'+ name; 
}

輸出

Output
廣告

© . All rights reserved.