Flutter for OpenHarmony:Dart 语法入门(上)附鸿蒙flutter演示
本文介绍了Dart编程语言及其在Flutter开发中的应用。Dart具有跨平台适配性、空安全特性和低学习成本三大优势,是Flutter唯一开发语言。文章详细讲解了Dart基础语法,包括程序入口main()函数、变量声明方式(强类型、var、dynamic)、常量声明(final和const)、字符串插值、运算符(基础运算和空值运算)以及流程控制(if/else、switch、循环)。最后通过Flu
目录
一、Dart 是什么?
Dart 是 Google 专为 Flutter 打造的强类型编程语言,也是 Flutter 唯一的开发语言。相比 Java / JavaScript,它有三个核心优势:
- 跨端适配性:编译后可直接运行在安卓、iOS、鸿蒙等多平台,完美匹配 Flutter “一套代码多端运行” 的目标;
- 空安全特性:从语法层面避免空指针崩溃;
- 上手成本低:语法融合了 Java 的强类型和 JavaScript 的灵活性,有任一语言基础都能快速入门。
二、基础语法
让我们打开上一篇中安装的 vscode 或 Trae ,创建一个以 .dart 为后缀名的文件,在这里面学习我们的基础语法,将语法学完之后,就可以配合 flutter 的组件,在 flutter 中编写代码了。
1. 程序入口:main () 函数
Dart 所有代码的执行入口都是 main() 函数,必须有且仅有一个。
// 最基础的Dart程序结构
void main() {
// 所有代码都写在这个函数体内
// 输出内容到控制台,python的写法,等同于Java的System.out.println
print("Hello Dart!");
}
注:
void表示函数无返回值,是main()函数的固定写法;- 语句结束必须加分号
;,Dart 严格区分大小写(比如
2. 变量声明:三种方式
变量的声明,格式:数据类型 变量名
可以在声明时直接给变量赋值,格式:数据类型 变量名 = 值 ;
int a = 10;
也可以先声明,之后赋值,格式:
数据类型 变量名 ;
变量名 = 值;
int b;
b = 10;
| 声明方式 | 示例 | 适用场景 |
|
强类型声明 (推荐) |
String name = "Flutter新手"; |
明确变量类型,代码易维护,减少出错 |
| var 自动推断 | var age = 20; | 类型可自动推断(赋值后不可改) |
| dynamic 任意类型 | dynamic temp = 100; | 不确定变量类型(赋值后可以改变) |
|
可空声明 类型?变量 |
String? name = null; | 可以赋空值 |
注:可空变量在赋给强类型时,要使用??判空
语法: a ?? b
如果 a 不为 null,就返回 a,如果 a 为 null,就返回 b。
具体的类型和使用方法都放到代码中进行演示
void main() {
// 1. 强类型声明(非空,必须赋值)
String userName = "张三"; // 字符串类型,不可为空
int userAge = 25; // 整型,只能存整数
double userHeight = 178.5; // 浮点型,存小数
bool isVip = false; // 布尔型,只有true/false两个值
// 错误示例:非空变量不能赋值为null
// userName = null; // 直接报错,空安全特性限制
// 2. 可空变量声明(加?表示可空)
String? nickName = null; // 允许赋值为null
nickName = "小张"; // 后续可修改为非空值
// 3. 使用??判空
String? name = null; //当这个变量允许赋值为null时,赋给强类型
String res = name ?? "默认名字"; //如果name不是null,res=name;
//如果name是null,res="默认名字"
// 4. var自动推断类型(赋值后类型固定)
var phone = "13800138000"; // 自动推断为String类型
// phone = 123; // 报错:不能将int赋值给String类型的变量
// 5. dynamic任意类型(慎用)
dynamic data = "初始值";
data = 123; // 可随意修改类型,无报错
data = true;
}
3. 常量:final vs const
常量是赋值后不可修改的值,Dart 有两种常量声明方式。
void main() {
// 1. final:运行时确定值,只能赋值一次
final String city = getCity(); // 可通过函数赋值(运行时才知道值)
// city = "上海"; // 报错:常量不可修改
// 2. const:编译时确定值,比final更严格
const double pi = 3.1415926; // 必须直接赋值固定值
// const String address = getAddress(); // 报错:const不能用运行时的值
// 实用场景:Flutter中定义固定尺寸、颜色常量
const double buttonWidth = 100.0;
const String baseUrl = "https://api.example.com";
}
// 模拟获取城市的函数
String getCity() {
return "北京";
}
核心区别:
final灵活,支持运行时赋值;const更严格,必须编译时确定值。
4. 打印变量
字符串插值:这是 Dart 中变量和字符串拼接的标准方式,语法简洁,支持所有变量类型(包括可空变量)。
核心格式
1. 基础格式:$变量名
例如:"字符串内容$变量名字符串内容"
2. 复杂格式:${表达式/变量}
例如:"字符串内容${表达式/变量}字符串内容"
更推荐使用第二种
import 'dart:io';
void main() {
// 普通变量
String name = "张三";
int age = 20;
print("姓名:$name,年龄:$age"); // 输出:姓名:张三,年龄:20
// 可空变量 + ?? 兜底
String? nickName = null;
print("昵称:${nickName ?? "匿名用户"}"); // 输出:昵称:匿名用户
// 表达式插值(大括号内可写运算/方法)
print("明年年龄:${age + 1}"); // 输出:明年年龄:21
print("姓名长度:${name.length}"); // 输出:姓名长度:2
}
5. 运算符:基础 + Dart 特色(空值运算符)
(1)基础运算符(和 Java/JS 一致)
void main() {
// 算术运算符:+ - * / %(取余)
int a = 10, b = 3;
print("a + b = ${a + b}"); // 13(加法)
print("a - b = ${a - b}"); // 7(减法)
print("a * b = ${a * b}"); // 30(乘法)
print("a / b = ${a / b}"); // 3.333...(除法,返回浮点型)
print("a ~/ b = ${a ~/ b}"); // 3(整数除法,只取商)
print("a % b = ${a % b}"); // 1(取余/模运算)
// 比较运算符:==、!=、>、<、>=、<= 返回布尔值
print("a == b → ${a == b}"); // false(等于:判断值是否相等)
print("a != b → ${a != b}"); // true(不等于:判断值是否不相等)
print("a > b → ${a > b}"); // true(大于)
print("a < b → ${a < b}"); // false(小于)
print("a >= b → ${a >= b}"); // true(大于等于)
print("a <= b → ${a <= b}"); // false(小于等于)
//字符串/其他类型的比较
String str1 = "dart";
String str2 = "Dart";
print("\n字符串比较:str1 == str2 → ${str1 == str2}"); // false(区分大小写)
// 逻辑运算符:&&(且)、||(或)、!(非)
bool isAdult = a > 18; // false(10>18不成立)
bool hasMoney = b > 0; // true(3>0成立)
print("isAdult && hasMoney → ${isAdult && hasMoney}"); // false(且:两边都为true才返回true)
print("isAdult || hasMoney → ${isAdult || hasMoney}"); // true(或:只要一边为true就返回true)
print("!isAdult → ${!isAdult}"); // true(非:取反)
}
(2)Dart 特色:空值运算符
空值运算符是 Dart 空安全的核心,能避免 90% 的空指针问题:
void main() {
String? nickName = null; // 可空变量
// 1. ?? 空值合并
String realName = nickName ?? "匿名用户";
print(realName); // 输出:匿名用户
// 2. ??= 空赋值
nickName ??= "默认昵称";
print(nickName); // 输出:默认昵称(已赋值)
nickName ??= "新昵称";
print(nickName); // 输出:默认昵称(非空,不赋值)
// 3. ?. 空安全调用(变量非空时才执行方法)
String? str = null;
print(str?.length); // 输出:null(str为空,不执行length)
str = "Flutter";
print(str?.length); // 输出:7(str非空,执行length)
}
6. 流程控制:if/else、循环
(1)if/else 条件判断
void main() {
int score = 85;
if (score >= 90) {
print("优秀");
} else if (score >= 80) {
print("良好");
} else if (score >= 60) {
print("及格");
} else {
print("不及格");
}
}
(2)switch case条件判断
void main() {
// 1. 基础示例:匹配整型值
int week = 3;
switch (week) {
case 1: // 匹配值=1
print("周一");
break; // 必须加break,否则会执行后续case(漏break导致穿透)
case 2:
print("周二");
break;
case 3:
print("周三");
break;
case 4:
case 5: // 多个case匹配同一逻辑,无需重复写代码
print("周中(周四/周五)");
break;
default: // 所有case都不匹配时执行
print("周末");
break;
}
// 2. Dart 特有:匹配字符串
String level = "B";
switch (level) {
case "A":
print("优秀");
break;
case "B":
print("良好");
break;
case "C":
print("及格");
break;
default:
print("不及格");
break;
}
}
(3)循环:for、while、forEach
List下一篇再讲,这里就把它当数组使用
void main() {
List<String> fruits = ["苹果", "香蕉", "橙子"]; //就是String类型的数组
// 1. 普通for循环(索引遍历)
for (int i = 0; i < fruits.length; i++) {
print("索引$i:${fruits[i]}"); // 字符串插值:用${}嵌入变量
}
// 2. for-in循环(遍历元素,推荐)
for (String fruit in fruits) {
print("水果:$fruit");
}
// 3. forEach循环(匿名函数,Flutter中最常用)
fruits.forEach((String fruit) {
print("forEach:$fruit");
});
// 4. while循环
int count = 0;
while (count < 3) {
print("count:$count");
count++;
}
}
三、flutter实战
Flutter 关联:forEach 是 Flutter 中遍历列表渲染 Widget 的核心写法,比如:
// Flutter中用forEach渲染列表项
List<Widget> getFruitWidgets() {
List<String> fruits = ["苹果", "香蕉", "橙子"];
List<Widget> widgets = [];
fruits.forEach((fruit) {
widgets.add(Text(fruit)); // 每个水果生成一个Text组件
});
return widgets;
}
现在看不懂没关系,之后用着用着就懂了,现在只是熟悉一下flutter。
打开大家创建的flutter项目,上一篇环境搭建时让大家创建了一个项目,使用vscode或Trae打开该文件夹。
找到 lib 文件夹下的 main.dart 文件,打开,把里面的代码全选,ctrl + ?注释掉。
把下面的代码粘贴上去,然后web的可以直接保持运行,鸿蒙的需要打开鸿蒙模拟器运行。
运行方法跟上一篇一样。
import 'package:flutter/material.dart';
// Flutter 程序入口(必须有)
void main() => runApp(const MyFruitApp());
// 根组件:整个App的入口组件
class MyFruitApp extends StatelessWidget {
const MyFruitApp({super.key});
@override
Widget build(BuildContext context) {
// MaterialApp 是 Flutter 基础布局框架
return MaterialApp(
title: '水果列表示例',
// 主页内容
home: Scaffold(
// 顶部导航栏
appBar: AppBar(
title: const Text('forEach 渲染列表'),
backgroundColor: Colors.blue,
),
// 页面主体内容(调用我们的列表渲染方法)
body: Center(
// 用 Column 垂直排列列表项,更易看效果
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// 调用 getFruitWidgets() 获取渲染后的Widget列表
children: getFruitWidgets(),
),
),
),
);
}
// 我们写的 getFruitWidgets 方法
List<Widget> getFruitWidgets() {
List<String> fruits = ["苹果", "香蕉", "橙子"];
List<Widget> widgets = [];
fruits.forEach((fruit) {
// 给 Text 加样式,看得更清楚(核心是 Text(fruit))
widgets.add(
Text(fruit),
);
});
return widgets;
}
}
实现效果

appBar是导航栏
在里面设置了 title(标题)为 “forEach 渲染列表”、背景颜色是蓝色。
body是页面主体
- 在里面放了个Center(居中)组件
- 在Center里面又放了个Column(垂直排列)组件,让内容垂直排列
- 在Column里面干了两件事,设置主要的对齐方式为:居中,调用我们写的函数
- 在函数里创建两个列表,一个String类型,一个Widget类型,flutter都是通过Widget类型进行显示,里面的组件都是Widget类型,所以我们的String类型列表要转换成Widget类型列表
- 通过forEach获取到fruits列表的每一个元素,放到fruit里面,然后把fruit设置成Text组件然后添加进widgets列表
- 最后返回widgets列表,这样我们在body中就能接收到整个列表,把里面的内容显示出来

也可以使用普通的for循环,只需要讲原来getFruitWidgets换成下面在段代码
List<Widget> getFruitWidgets() {
int a = 10;
int b = 20;
List<Widget> widgets = [];
for (int i = 0; i < 5; i++) {
widgets.add(
Text("这是第${i + 1}个数,a=${a},b=${b},a+b=${a + b}"),
);
a += i; // 等同于 a = a +i
b += i;
}
return widgets;
}
}
实现效果
将之前的内容换成了我们for循环里的内容

这样就将前面的知识稍微联系起来了
结尾
通过本篇学习,你已经掌握了 Dart 最核心的基础语法,掌握变量、常量、流程控制、空安全基础,并且附带了flutter的演示;对于flutter看不懂没关系,慢慢来,只有先了解基础语法,才能进行项目开发。
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)