Dart快速入门到上手Flutter

1. Dart是什么?

Dart是一种适用于万维网的开放源代码编程语言,由Google主导开发,于2011年10月公开。它的开发团队由Google Chrome浏览器V8引擎团队的领导者拉尔斯·巴克主持,目标在于成为下一代结构化Web开发语言。 类似JavaScript,Dart也是一种面向对象语言,但是它采用基于类的编程。

众所周知,使用JavaScript编写项目,尤其是当项目过大并且几个人同时开发时,因为JavaScript是弱类型语言,又因为ajax的出现,很多数据都是通过后端返回到前端,随着时间一长或者原开发人员的离职,后面接手项目的人员可能并不知道后端传来的数据中到底有什么。

JavaScript因为是弱类型,提示也非常不智能,后端返回的数据往往是一个JSON格式,而将它解析成一个对象并且在项目中调用这个对象时,使用xxx.xxx的形式,你不会得到智能提示,这也导致在开发过程中很可能将属性名字打错,尤其是在字段名较长的情况下,即使是经验丰富的程序员可能都会在这上面犯错。

有时候一个有值的属性却打印出来是undefined,检查了半天发现是自己的属性名称打错,场面非常尴尬。

而Google就想要开发一种编程语言,来解决JavaScript这些痛点,它就是Dart,但是不知道是大家对JavaScript爱的深沉还是因为前端开发者大多都已经习惯了这种高自由的编写代码的感觉,不喜欢被类型所束缚,Dart最终是没有比过TypeScript,而陷入了沉浸。

直到Flutter的出现,Dart开始重新回到人们的视野中,也正因为Flutter的出现,完成了一套代码在Android和iOS上运行的表现几乎一致,并且性能更接近原生APP性能。

本篇文章主要盘点一下,Dart和JavaScript有哪些区别。

2. 开始Dart之旅

2.1 安装

Dart在mac和linux上面的安装还是挺简单,而windows上面的安装直接进入到:windows安装,下载后直接选择下一步就好:

image-20210124225505515

之前我去到Dart官网进行下载,发现环境配置起来还是有点麻烦,不如这种exe文件省事。

2.2 IDE

VSCode安装上这两个插件就可以直接开撸,Dart文件的后缀名是.dart

image-20210124225758088

image-20210124225922878

3. main函数

Dart和JavaScript第一点不同就是它必须拥有一个main函数,同时main函数也是Dart的入口函数。

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

4. 声明常量

4.1 final关键字

final是用来声明一个常量,可以在声明的时候不进行赋值,在之后再进行赋值:

void main() {
  final a;
  a = 100;
  print(a);
}

4.2 const关键字

经过一次赋值后就无法再次进行赋值,如果再次赋值就会报错,这一点和final一致,但是const关键字必须要在声明的时候就进行赋值。

void main() {
  const a = 100;
  print(a);
}

5. 字符串

和JavaScript不同的是,字符串可以使用三引号来进行多行声明"""多行声明"""

void main() {
  String a = """
  这是一个多行声明
  使用三引号可以进行换行""";
  print(a);
}

5.1 拼接

字符串的拼接有点类似于JavaScript中的``模板语法。

void main() {
  String a = "Hello ";
  String b = "World!";
  print("$a$b");
}

可以使用$a表示变量,也可以使用JavaScript模板语法中的${a}表示变量,这都是可行的,同时也可以使用+来进行字符串拼接。

void main() {
  String a = "Hello ";
  String b = "World!";
  print(a + b);
}

上面这两种拼接方式都是可行的。

6. 数字类型

Dart中的数字类型和Java、C#这种静态语言相似,都有整形和浮点型。

6.1 int整形

int类型的变量只能赋值一个整数,不能赋值一个小数,如果赋值小数会报错。

6.2 double浮点型

double类型既可以赋值一个整数,也可以赋值一个小数,但是如果赋值一个整数会默认带有一位小数。

void main() {
  int a = 100;
  double b = 100;
  print(a + b); // 200.0
}

7. is关键字

用来判断一个变量是什么类型。

void main() {
  var str = "Hello";
  if (str is String) {
    print("是string类型");
  } else if (str is int) {
    print("是int类型");
  } else {
    print("其它类型");
  }
}

这个在判断后端传来的数据时非常有用。

8. 算术运算符

8.1 a%b

两值相除,取余。

void main() {
  var a = 300;
  var b = 200;
  print(a % b); // 100
}

8.2 a~/b

两值相除,取整。

void main() {
  var a = 300;
  var b = 200;
  print(a ~/ b); // 1
}

9. 赋值运算符

9.1 ??=

如果变量为null,则将=后面的值赋值给变量,如果不为null则不进行赋值。

void main() {
  var a;
  a ??= 100;
  print(a); // 100
}

该运算符我觉得是非常有用的,因为当从后端接收一个数据,你并不知道后端是否会返回null,如果返回null你可能一用就会报错,所以这个时候你可以给它赋一个默认值。

10. 可选参数

在声明函数时我们可以使用可选参数,用[]进行声明。

void main() {
  optional("张三");
}

void optional(String name, [var sex]) {
  print(name); // 张三
  print(sex); // null
}

同时我们还可以给可选参数一个默认值:

void main() {
  optional("张三");
}

void optional(String name, [var sex = 213]) {
  print(name); // 张三
  print(sex); // 213
}

11. 箭头函数

Dart中的箭头函数不像JavaScript中的箭头函数那样,肩上扛着巨大的历史包袱。

Dart中的箭头函数仅仅是用来表示一个匿名函数只有一条语句,并且箭头函数只能有一条语句,如果超过一条语句会报错。

void main() {
  var a = () => print("箭头函数");
  a();
}

如果要声明一个多条语句的匿名函数,则需要去掉箭头。

void main() {
  var a = () {
    print("匿名函数");
    print("这是多条语句");
  };
  a();
}

12. 面向对象

相信写JavaScript的开发者大多数人都不会在自己的项目中使用到面向对象这种编程方式,如果一个开发者接触的第一门语言是面向对象语言的话,例如Java、C#、C++就会比较喜欢面向对象这种编程方式。

反之,如果第一门语言是JavaScript这种脚本语言的开发者,极少数会在自己的项目中使用面向对象编程。

当然上面的结论仅仅是我在论坛这些地方观察得到…因为React和Vue已经开始拥抱函数式编程了。

12.1 构造函数

12.1.1 默认构造函数

class Person {
  String name;
  int age;

  Person(this.name, this.age); // 构造函数

  void printInfo() {
    print("${this.name}${this.age}岁");
  }
}

void main() {
  Person p1 = Person("张三", 123);
  p1.printInfo();
}

12.1.2 命名构造函数

class Person {
  String name;
  int age;

  Person(this.name, this.age); // 默认构造函数

  Person.name(this.name, this.age); // 命名构造函数

  void printInfo() {
    print("${this.name}${this.age}岁");
  }
}

void main() {
  Person p1 = Person("张三", 123);
  Person p2 = Person.name("张三", 123);
  p1.printInfo();
  p2.printInfo();
}

12.1.3 初始化实例变量

在构造函数后面还可以跟:后面给变量进行初始化赋值。

注:赋值在实例化之前。

class Person {
  String name;
  int age;

  Person()
      : name = "张三",
        age = 10; // 初始化实例变量

  void printInfo() {
    print("${this.name}${this.age}岁");
  }
}

12.2 私有方法

class Person {
  late String name;
  late int _age; // 私有
}

在变量名前添加_即代表该属性或者方法为私有,但是在同一个文件中不会生效,必须在不同的文件中才能生效。

12.3 ..

级联操作符,在对实例进行赋值的时候非常有用。

class Person {
  late String name;
  late int age;

  void printInfo() {
    print("${this.name}${this.age}岁");
  }
}

void main() {
  Person p1 = Person();
  p1
    ..name = "张三"
    ..age = 10;  // 级联操作符
}

12.4 @override

当重写父类的方法时,建议在方法上面加上@override表示这是重写的方法。

class Person {
  late String name;
  late int age;

  void printInfo() {
    print("${this.name}${this.age}岁");
  }
}

class Men extends Person {
  @override
  void printInfo() {
    print("这是重写的方法");
  }
}

12.5 抽象类

抽象类不能被实例化,它是用来约束一个类,关键字为abstract,当一个类继承一个抽象类后,就必须实现抽象类中的方法。

abstract class Person {
  void printInfo();
}

class Men extends Person {
  @override
  void printInfo() {
    // TODO: implement printInfo
  }
}

面向对象部分的某些概念是非常复杂生涩和难懂的,大概知道这个东西,等到用到的时候再学就可以了。

所以这里也就不展开讲解Dart中的多态。

12.5.1 接口

Dart和其它面向对象的语言不通,它没有专门定义接口的方法,只有使用类或者抽象类来定义接口,关键字为implements

abstract class Person {
  late String name;
  late int age;

  void printInfo();
}

class Men implements Person {
  @override
  void printInfo() {
    // TODO: implement printInfo
  }

  @override
  late int age;

  @override
  late String name;
}

12.6 mixins

关键字为with

  1. 作为mixis的类只能继承自object,不能继承其它类。
  2. 作为mixis的类不能有构造函数。
  3. 一个类可以mixins多个mixins类。
  4. mixins绝不是继承,也不是接口,而是一种全新的特性。
class A {
  void printInfo() {
    print("这是A类");
  }
}

class B {
  void printInfo() {
    print("这是B类");
  }
}

class C with A, B {}

as

类型断言,当你比编辑器更明白该变量为什么类型时,你就可以使用as关键字进行类型断言,从而获得提示。

不进行类型断言:

image-20210125202733011

进行类型断言:

image-20210125202717936

13. 最后

其实Dart的入门并不难,如果有其它语言的基础,尤其是静态编程语言,那么花几天时间大致看看Dart的一些特性就可以开始学习Flutter了,毕竟Flutter才是学习Dart的目的。

如果仅有JavaScript的基础,那可能会因为类型约束而感到不适。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!