本文學習和引用自《Flutter實戰(zhàn)·第二版》:作者:杜文
1. 變量聲明
- var
類似于 JavaScript 中的var,它可以接收任何類型的變量,但最大的不同是 Dart 中 var 變量一旦賦值,類型便會確定,則不能再改變其類型:
var name = "李四"
/// 對
name = "張三"
/// 錯
name = 1000
- Object
Object 是 Dart 所有對象的根基類,也就是說在 Dart 中所有類型都是Object的子類(包括Function和Null),所以任何類型的數據都可以賦值給Object聲明的對象,且后期可以改變賦值的類型。但是聲明的對象只能使用 Object 的屬性與方法, 否則編譯器會報錯。
Object t = 1000
t = "張三"
print(t.length) // 錯
- dynamic
任何類型的數據都可以賦值給dynamic聲明的對象,且聲明的變量都可以賦值任意對象,且后期可以改變賦值的類型。而編譯器會提供所有可能的組合給聲明的對象,這個特點使得我們在使用它時需要格外注意,比如下面代碼在編譯時不會報錯,而在運行時會報錯:
dynamic t
t = "王五"
print(t.xxx) // 錯
- final
如果您從未打算更改一個變量,那么可以使用 final。一個 final 變量只能被設置一次。它是一個運行時常量,final變量在運行時才知道其值,用于防止變量在程序運行期間被改變。
- const
如果您從未打算更改一個變量,那么可以使用 const。與final的區(qū)別是,const 變量是一個編譯時常量,其值必須在聲明時就確定。(編譯時直接替換為常量值)用于創(chuàng)建編譯時常量,以便進行性能優(yōu)化。
- 空安全
Dart 中一切都是對象,這意味著如果我們定義一個數字,在初始化它之前如果我們使用了它,假如沒有某種檢查機制,則不會報錯。如下:
test() {
int i;
print(i*8); // 錯
}
在 Dart 引入空安全之后,如果一個變量沒有初始化,則不能使用它,否則編譯器會報錯:
int a = 10
聲明時候可以加上?,指定變量是可空:
String? name;
如果我們預期變量不能為空,但在定義時不能確定其初始值,則可以加上late關鍵字,表示會稍后初始化,但是在正式使用它之前必須得保證初始化過了,否則會報錯:
late int c;
c = 100
如果一個變量我們定義為可空類型,且判空了,但是預處理器仍然有可能識別不出,這時我們就要在變量后面加一個!符號,告訴預處理器它已經不是null了。
class Test() {
int? d;
log() {
if (d! = null) {
print(d! * 100)
}
}
}
如果函數變量可空時,調用的時候可以用語法糖:
fun?.call()
- 特殊聲明模式
// 同時聲明
var (a, [b, c]) = ('str', [1, 2])
// 同時聲明
var (c, d) = ('left', 'right');
// 交換2個值
(c, d) = (d, c)
// 解構
var (name, age) = userInfo(json)
// 省略符
var (a, b, ...rest) = [1, 2, 3, 4, 5, 6] // 1 2 [3,4,5,6]
var (a, b, ...rest, c, d) = [1, 2, 3, 4, 5, 6] // 1 2 [3,4] 5 6
var (a, b, ..., c, d) = [1, 2, 3, 4, 5, 6] // 1 2 5 6
2. 操作符
- 算數運算符
| 符號 | 意義 | 描述 |
|---|---|---|
| + | 加 | - |
| - | 減 | - |
| * | 乘 | - |
| / | 除 | - |
| ~/ | 除 | 返回整數結果 |
| % | 取余 | 獲取整數除法的余數 |
- 等于運算符
| 符號 | 意義 | 描述 |
|---|---|---|
| == | 平等 | - |
| != | 不相等 | - |
| > | 大于 | - |
| < | 小于 | - |
| >= | 大于或等于 | - |
| <= | 小于或等于 | - |
- 邏輯運算符
| 符號 | 意義 | 描述 |
|---|---|---|
| ! | 反轉 | - |
| 或者 | - | |
| && | 并且 | - |
- 賦值運算符
| 符號 | 意義 | 描述 | |
|---|---|---|---|
| = | 賦值 | - | |
| *= | 乘法賦值 | - | |
| += | 加法賦值 | - | |
| -= | 減法賦值 | - | |
| /= | 除法賦值 | - | |
| %= | 取模賦值 | - | |
| ~/= | 返回除法整數結果賦值 | - | |
| = | 按位或賦值 | - | |
| &= | 按位與賦值 | - | |
| ^= | 按位異或賦值 | - | |
| <<= | 左移賦值 | - | |
| >>= | 右移賦值(保留符號位) | - | |
| >>>= | 右移賦值(無符號右移) | - |
- 類型運算符
| 符號 | 意義 | 描述 |
|---|---|---|
| as | 類型轉換斷言 | - |
| is | 如果對象具有指定的類型,則為 True | - |
| is! | 如果對象沒有指定的類型,則為 True | - |
// 如果您不確定該對象的類型是否為Person,則在使用對象之前用is檢查
if (employee is Person) {
employee.firstName = 'Bob';
}
- 按位運算符
| 符號 | 意義 | 描述 |
|---|---|---|
| & | 與 | - |
| | | 或 | - |
| ^ | 異或 | - |
| << | 左移 | - |
| >> | 右移 | - |
| >>> | 無符號右移 | - |
- 條件表達式
| 語法 | 意義 | 描述 |
|---|---|---|
| condition ? expr1 : expr2 | 賦值 | 三元表達式 |
| expr1 ?? expr2 | 賦值 | 如果 expr1 為非 null,則返回其值; 否則,計算并返回 expr2 的值 |
| ?.xxx | 短路 | 條件成員訪問 |
| ! | 斷言 | 將表達式強制轉換為其基礎不可為 null 的類型 |
- 級聯表示法
級聯允許您在同一對象上,進行一系列操作。
// 級聯語法
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
// 等價于如下語法
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
// 級聯語法
querySelector('#confirm')
?..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'))
..scrollIntoView();
// 等價于如下語法
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();
3. 數據類型
| 關鍵字 | 描述 |
|---|---|
| int | 不大于 64 位的整數值 |
| double | 64 位(雙精度)浮點數 |
| String | 字符串,多行字符串可以用'''xxx''' |
| bool | 字符串 |
| Set | 集 |
| Map | 地圖 |
| List | 列表 |
| Symbol | 符號 |
| Null | null |
| record | 記錄 |
| typedef | 類型別名 |
4. 控制流
- switch
int size = 2;
// 條件判斷
switch (size) {
case 1:
print('一');
case [2, 3]:
print('二 and 三')
case [4 || 5]:
print('四 or 五')
case >= 6 && <= 10
print('六 to 十')
}
// 條件賦值
var bg = Color.green
var isPrimary = switch (bg) {
Color.red || Color.yellow || Color.blue => true,
_ => false
}
- for
var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}
- fon-in
Map<String, int> listMap = {
'a': 23,
'b': 100,
};
for (final MapEntry(key: key, value: value) in listMap.entries) {
print('鍵:$key 值:$value');
}
- while
while (!isDone()) {
doSomething();
}
- do-while
do {
printLine();
} while (!atEndOfPage());
- 跳過和停止
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
- if
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
- if-case
// 接受一個名為pair的參數。如果pair的類型是[int x, int y],則返回一個Point(x, y)對象
if (pair case [int x, int y]) return Point(x, y);
5. 錯誤處理和捕獲
異常捕獲和JavaScript差不多
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 特定的異常
buyMoreLlamas();
} on Exception catch (e) {
// 任何其他的例外
print('Unknown exception: $e');
} catch (e) {
// 沒有指定類型,處理所有類型
print('Something really unknown: $e');
} finally {
cleanLlamaStalls();
}
- 若要部分處理異常, 同時允許它傳播, 使用關鍵字:rethrow
void misbehave() {
try {
dynamic foo = true;
print(foo++); // 運行時錯誤
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // 允許調用者看到異常
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
- 斷言
在開發(fā)過程中,使用斷言語句,如果布爾條件為false,則觸發(fā)。如果條件為true,則不觸發(fā)。在生產代碼中,斷言將被忽略。
// assert(條件, 可選消息)
var sizi = 101;
assert(size < 100, "Error:size 小于 100!");
6. 函數
Dart是一種真正的面向對象的語言,所以即使是函數也是對象,并且有一個類型Function。這意味著函數可以賦值給變量或作為參數傳遞給其他函數,這是函數式編程的典型特征。
- 函數聲明
bool isNoble(int ) {
return atomicNumber > 40;
}
bool isNoble (int atomicNumber) => atomicNumber > 40;
- 函數作為參數傳遞
//定義函數execute,它的參數類型為函數
void execute(var callback) {
// 執(zhí)行傳入的函數
callback();
}
// 調用execute,將箭頭函數作為參數傳遞
execute(() => print("xxx"))
- 可選的位置參數
String say(String a, String b, [String? c]) {
var result = '$a and $b';
if (c != null) {
result = '$result and $c';
}
return result;
}
- 可選的命名參數
//設置[a]和[b]標志
void enableFlags({bool a, bool b}) {
// ...
}
// 調用函數時,可以使用指定命名參數
enableFlags(bold: true, hidden: false)
7. mixin
Dart 是不支持多繼承的,但是它支持 mixin??梢远x幾個 mixin,然后通過 with 關鍵字將它們組合成不同的類(同名會被最后的覆蓋)。如下例子:
class Person {
say() {
print('say');
}
}
mixin Eat {
eat() {
print('eat');
}
}
mixin Walk {
walk() {
print('walk');
}
}
mixin Code {
code() {
print('key');
}
}
class Dog with Eat, Walk{}
class Man extends Person with Eat, Walk, Code{}
8. 異步
Dart類庫有非常多的返回Future或者Stream對象的函數,這些函數被稱為異步函數。
8-1. Future
Future與JavaScript中的Promise非常相似。
// 使用Future.delayed 創(chuàng)建了一個延時任務,2秒后返回結果字符串,然后在then中接收異步結果并打印
Future.delayed(Duration(seconds: 2),(){
return "hi world!";
}).then((data){
// 執(zhí)行成功
print(data);
}).catchError((e){
//執(zhí)行失敗會走到這里
print(e);
}).whenComplete((){
//無論成功或失敗都會走到這里
});
- 多個異步:Future.wait
Future.wait([
// 2秒后返回結果
Future.delayed(Duration(seconds: 2), () {
return "hello";
}),
// 4秒后返回結果
Future.delayed(Duration(seconds: 4), () {
return " world";
})
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
- 解決回調地獄:async/await
task() async {
try{
String id = await login("alice","******");
String userInfo = await getUserInfo(id);
await saveUserInfo(userInfo);
// 執(zhí)行接下來的操作
} catch(e){
// 錯誤處理
print(e);
}
}
8-2. Stream
Stream 也是用于接收異步事件數據,和 Future 不同的是,它可以接收多個異步操作的結果(成功或失敗)。 也就是說,在執(zhí)行異步任務時,可以通過多次觸發(fā)成功或失敗事件來傳遞結果數據或錯誤異常。 Stream 常用于會多次讀取數據的異步任務場景,如網絡內容下載、文件讀寫等。
Stream.fromFutures([
// 1秒后返回結果
Future.delayed(Duration(seconds: 1), () {
return "hello 1";
}),
// 拋出一個異常
Future.delayed(Duration(seconds: 2),(){
throw AssertionError("Error");
}),
// 3秒后返回結果
Future.delayed(Duration(seconds: 3), () {
return "hello 3";
})
]).listen((data){
print(data);
}, onError: (e){
print(e.message);
},onDone: (){});
// 上述代碼依次輸出
// hello 1
// Error
// hello 3
本次分享就到這兒啦,我是@鵬多多,如果您看了覺得有幫助,歡迎評論,關注,點贊,轉發(fā),我們下次見~
PS:在本頁按F12,在console中輸入document.querySelectorAll('._2VdqdF')[0].click(),有驚喜哦
往期文章
- flutter學習-day1-環(huán)境搭建和啟動第一個項目
- 超詳細的Cookie增刪改查
- 助你上手Vue3全家桶之Vue3教程
- 助你上手Vue3全家桶之VueX4教程
- 助你上手Vue3全家桶之Vue3教程
- 超詳細!Vuex手把手教程
- 使用nvm管理node.js版本以及更換npm淘寶鏡像源
- 超詳細!Vue-Router手把手教程
- vue中利用.env文件存儲全局環(huán)境變量,以及配置vue啟動和打包命令
- 微信小程序實現搜索關鍵詞高亮
個人主頁