← Frontend / Flutter

00_Dart语言速学

Dart 编程语言快速入门

Dart 是 Flutter 的编程语言。语法和 TypeScript 非常接近,JS 开发者上手成本很低。本章专为已会 JS/TS 的开发者设计,重点标注差异点。


变量与类型

// Dart 有健全的空安全(Sound Null Safety)— 类似 TypeScript 的严格模式
String name = 'Flutter';      // 不可为 null
String? nickname;             // ? 表示可为 null(对比 TS: string | null)
int age = 25;
double pi = 3.14;
bool isReady = true;
var count = 0;                // 类型推断,等同于 int count = 0

// final:运行时常量(类似 JS const,但赋值后不可改)
final String version = '3.0';

// const:编译期常量(Flutter 中大量用于 Widget 优化)
const double gravity = 9.8;

对比 JS: Dart 没有 undefined,空值只有 null,且必须显式声明可空类型(?),大幅减少空指针错误。


集合类型

// List(对应 JS Array)
List<String> fruits = ['apple', 'banana', 'cherry'];
var nums = [1, 2, 3];            // 推断为 List<int>
nums.add(4);
nums.removeAt(0);
print(nums.length);              // 3

// Map(对应 JS Object / Map)
Map<String, dynamic> user = {'name': 'Alice', 'age': 30};
user['email'] = 'alice@example.com';
print(user['name']);             // Alice

// Set(不重复集合)
Set<String> tags = {'flutter', 'dart', 'mobile'};
tags.add('flutter');             // 重复,不会添加
print(tags.length);              // 3

函数

// 普通函数
int add(int a, int b) {
  return a + b;
}

// 箭头函数(单行表达式)
int multiply(int a, int b) => a * b;

// 命名参数(类似 JS 解构传参,Flutter 中最常见写法)
void greet({required String name, int age = 18}) {
  print('Hello $name, age: $age');
}
greet(name: 'Bob');              // 调用时必须写参数名
greet(name: 'Alice', age: 25);

// 可选位置参数
String format(String msg, [String prefix = '']) => '$prefix$msg';

// 函数是一等公民(和 JS 一样)
var fn = (int x) => x * 2;
print(fn(5));                    // 10

类与面向对象

class Person {
  final String name;
  int age;

  // 构造函数简写:this.xxx 自动赋值
  Person({required this.name, required this.age});

  // 命名构造函数(类似工厂方法)
  Person.guest() : name = 'Guest', age = 0;

  void introduce() {
    print('I am $name, age $age');
  }

  // getter(对比 Vue computed)
  String get info => '$name ($age)';
}

// 继承
class Student extends Person {
  final String school;

  Student({required super.name, required super.age, required this.school});

  @override
  void introduce() {
    super.introduce();
    print('School: $school');
  }
}

// 使用
final p = Person(name: 'Alice', age: 25);
final s = Student(name: 'Bob', age: 20, school: 'MIT');

异步编程(async / await)

// Dart 的 async/await 与 JS 几乎完全相同!
// Future = JS 的 Promise
Future<String> fetchUser() async {
  await Future.delayed(const Duration(seconds: 1));  // 模拟延迟
  return 'Alice';
}

// 调用
Future<void> main() async {
  final user = await fetchUser();
  print(user);  // Alice
}

// 错误处理(与 JS try/catch 相同)
Future<void> loadData() async {
  try {
    final result = await fetchUser();
    print(result);
  } catch (e) {
    print('Error: $e');
  }
}

// Stream = JS 的 AsyncGenerator / RxJS Observable(连续数据流)
Stream<int> countDown(int n) async* {
  for (int i = n; i >= 0; i--) {
    yield i;
    await Future.delayed(const Duration(seconds: 1));
  }
}

// 消费 Stream
countDown(5).listen((value) => print(value));

空安全操作符

String? name;                    // 可为 null

// ?. 安全调用(与 JS 可选链 ?. 相同)
int? len = name?.length;         // name 为 null 时返回 null

// ?? 空值合并(与 JS 相同)
String display = name ?? '匿名用户';

// ! 非空断言(确信不为 null,类似 TS 的 !)
String definite = name!;         // name 为 null 时抛出异常,慎用

// ??= 空值赋值
name ??= '默认名称';             // name 为 null 时才赋值

Dart 独有特性

// 字符串插值
String msg = 'Hello $name, 2+2=${2+2}';

// 级联操作符 ..(链式调用,避免重复写变量名)
var buffer = StringBuffer()
  ..write('Hello')
  ..write(' ')
  ..write('World');
print(buffer.toString());  // Hello World

// spread 扩展(类似 JS ...)
var list1 = [1, 2, 3];
var list2 = [0, ...list1, 4];   // [0, 1, 2, 3, 4]

// collection if / collection for — 在 Widget 树中极常用!
var items = [
  'a',
  if (isLoggedIn) 'profile',              // 条件元素
  for (final tag in tags) '#$tag',        // 循环元素
];

与 JavaScript 快速对比

JS / TS Dart 说明
let / const var / final / const const = 编译期常量
string | null String? 空安全
Promise<T> Future<T> 异步值
AsyncGenerator Stream<T> 异步序列
interface abstract class 抽象类
type Fn = () => void typedef Fn = void Function() 函数类型别名
console.log print 打印
Array.map() list.map().toList() 需要 .toList() 转回 List
Object.keys() map.keys.toList()
解构 const {a} = obj 无直接语法,用 obj.a
可选链 ?. ?. 相同
空值合并 ?? ?? 相同