美文网首页
Flutter学习(三)Dart语法汇总

Flutter学习(三)Dart语法汇总

作者: yanhooIT | 来源:发表于2020-03-26 12:14 被阅读0次

    内部团队学习,以简单直接为主

    Dart差异化语法说明

    • 这里是从一个有1-2年移动端开发经验的开发者视角总结的Dart语法
    • 这里只会说一些差异化的语法,类似的语法就不在说了

    学习工具配置

    • 我在学习Dart语法选择了VSCode这个工具,因为他比较轻量级,首先在这里下载VSCode
    • 安装插件,我安装了Flutter、Dart、Code Runner、Chinese以及一个Theme,如下图 VSCode插件安装

    在VSCode中添加dart文件

    • 直接新建xxx.dart文件即可
    • 每个dart文件中必须显式添加入口函数main函数

    入口main函数

    • 新建helloDart.dart文件
    • 添加main函数,代码如下:
    main(List<String> args) {
      // dart打印用print函数
      print('Hello Dart');
    }
    
    • 在终端执行dart helloDart.dart,就能看到Hello Dart的结果了

    定义变量

    明确声明(Explicit)

    • 格式:变量类型 变量名称 = 赋值;
    • 定义的变量可以修改值, 但是不能赋值其他类型
    • 代码示范
      String name = "yanhoo";
    
      // 可以随时被修改
      name = "yety";
    
      // 不允许赋值其他类型
      // name = 19;
    

    类型推导(Type Inference)

    • 格式:var/dynamic/const/final 变量名称 = 赋值;
    • var
      • 类型推导的方式虽然没有明确的指定变量的类型, 但是变量是有自己的明确的类型
      • 代码示范
      var age = 20;
      age = 30;
      
      // 不可以将String赋值给一个int类型
      // age = "abc";
      
      // runtimeType用于获取变量当前的类型
      print(age.runtimeType);
      
    • dynamic
      • 类型动态化,开发中不建议使用,会存在隐患
      • 示例代码
      dynamic name = 'yanhoo';
      print(name.runtimeType);// String
      name = 18;
      print(name.runtimeType);// int
      
    • final声明的常量
      • final在赋值时, 可以运行时动态获取, 比如赋值一个函数
      • final一旦被赋值后就有确定的结果, 就不允许再次赋值
      • 示范代码
      final time = DateTime.now();
      // 再次赋值是不允许的
      // final time = DateTime.now();
      
    • const声明常量
      • const在赋值时, 赋值的内容必须是在编译期就确定下来的
      • 示范代码
      const name = 'yanhoo';
      // 再次赋值是不允许的
      // const name  = 'yety';
      
    • const声明常量构造函数
    main(List<String> args) {
      // 这样就可以赋值给const修饰的变量
      const p1 = Person("yanhoo");
      const p2 = Person("yanhoo");
      const p3 = Person("yety");
    
      print(identical(p1, p2));// true
      print(identical(p2, p3));// false
    }
    
    class Person {
      // 常量构造函数中的成员变量必须使用final修饰
      final String name;
      // 常量构造函数
      const Person(this.name);
    }
    

    数据类型

    • 占位符:${expression}(如果表达式是一个标识符, 那么{}可以省略),用于字符串、其他变量以及表达式的拼接
    • 数值类型
      • 对于数值来说,我们也不用关心它是否有符号,以及数据的宽度和精度等问题。只要记着整数用int,浮点数用double就行了,Dart中的int和double可表示的范围并不是固定的,它取决于运行Dart的平台
      • 字符串和数字之间的转化
      // 1.字符串转数字
       var one = int.parse('111');
      var two = double.parse('12.22');
      print('${one} ${one.runtimeType}'); // 111 int
      print('${two} ${two.runtimeType}'); // 12.22 double
      
      // 2.数字转字符串
      var num1 = 123;
      var num2 = 123.456;
      var num1Str = num1.toString();
      var num2Str = num2.toString();
      var num2StrD = num2.toStringAsFixed(2); // 保留两位小数
      print('${num1Str} ${num1Str.runtimeType}'); // 123 String
      print('${num2Str} ${num2Str.runtimeType}'); // 123.456 String
      print('${num2StrD} ${num2StrD.runtimeType}'); // 123.46 String
      
    • 布尔类型:Dart中不能判断非0即真, 或者非空即真,你必须给出明确的布尔值,其他也没什么好说的
    • 字符串类型
    // 1、Dart字符串是UTF-16编码单元的序列。您可以使用单引号或双引号创建一个字符串
    var s1 = 'Hello World';
    var s2 = "Hello Dart";
    var s3 = 'Hello\'Fullter';
    var s4 = "Hello'Fullter";
    
    // 2、可以使用三个单引号或者双引号表示多行字符串
    var message1 = '''
    哈哈哈
    呵呵呵
    嘿嘿嘿''';
    
    • 集合类型:List / Set / Map,这个也没啥好说的,下面用代码的方式说一下各自的定义和一些基本用法
    // ----------------- List定义 -----------------
    // 1.使用类型推导定义
    var letters = ['a', 'b', 'c', 'd'];
    print('$letters ${letters.runtimeType}');
    
    // 2.明确指定类型
    List<int> numbers = [1, 2, 3, 4];
    print('$numbers ${numbers.runtimeType}');
    
    // Set和List最大的两个不同就是:Set是无序的,并且元素是不重复的
    
    // ----------------- Set定义 -----------------
    // 1.使用类型推导定义
    var lettersSet = {'a', 'b', 'c', 'd'};
    print('$lettersSet ${lettersSet.runtimeType}');
    
    // 2.明确指定类型
    Set<int> numbersSet = {1, 2, 3, 4};
    print('$numbersSet ${numbersSet.runtimeType}');
    
    // ----------------- Map定义 -----------------
    // 1.使用类型推导定义
    var infoMap1 = {'name': 'xxx', 'age': 18};
    print('$infoMap1 ${infoMap1.runtimeType}');
    
    // 2.明确指定类型
    Map<String, Object> infoMap2 = {'height': 1.88, 'address': '北京市'};
    print('$infoMap2 ${infoMap2.runtimeType}');
    
    • 集合的常见操作,直接上代码
    // ----------------- List 和 Set的操作 -----------------
    // 获取集合的长度
    print(lettersList.length);
    print(lettersSet.length);
    print(infoMap.length);
    
    // 添加/删除/包含元素
    numbersList.add(5);
    numbersSet.add(5);
    print('$numbersList $numbersSet');
    
    numbersList.remove(1);
    numbersSet.remove(1);
    print('$numbersList $numbersSet');
    
    print(numbersList.contains(2));
    print(numbersSet.contains(2));
    
    // List由于是有序的,所以可以根据index删除元素
    numbersList.removeAt(3);
    print('$numbersList');
    
    // ----------------- Map的操作 -----------------
    // 1.根据key获取value
    print(infoMap1['name']);
    
    // 2.获取所有的entries
    print('${infoMap1.entries} ${infoMap1.entries.runtimeType}'); // (MapEntry(name: xxx), MapEntry(age: 18)) MappedIterable<String, MapEntry<String, Object>>
    
    // 3.获取所有的keys
    print('${infoMap1.keys} ${infoMap1.keys.runtimeType}'); // (name, age) _CompactIterable<String>
    
    // 4.获取所有的values
    print('${infoMap1.values} ${infoMap1.values.runtimeType}'); // (xxx, 18) _CompactIterable<Object>
    
    // 5.判断是否包含某个key或者value
    print('${infoMap1.containsKey('age')} ${infoMap1.containsValue(18)}'); // true true
    
    // 6.根据key删除元素
    infoMap1.remove('age');
    print('${infoMap1}'); // {name: xxx}
    

    函数

    概述

    • Dart是一种真正的面向对象语言,所以函数也是对象,也有类型,类型为Function
    • 函数可以作为变量定义或者作为其他函数的参数或者返回值

    函数的定义

    返回值 函数的名称(参数列表) {
      // coding...
      return 返回值;
    }
    
    // 示例
    int sum(int num1, int num2) {
      return num1 + num2;
    }
    
    // 也可以这么写(不推荐)
    sum(num1, num2) {
      return num1 + num2;
    }
    
    // 如果函数体只有一句,可以使用箭头函数
    // 箭头函数不允许以分号结尾,上面的可以这样写
    sum(int num1, int num2) => num1 + num2
    

    函数的参数

    • 必填参数,如下:
    int sum(int num1, int num2) {
      return num1 + num2;
    }
    
    • 可选参数:命名可选参数位置可选参数,个人更加偏好命名可选参数
      • 命名可选参数定义方式:{param1, param2, ...}
      // 命名可选参数
      printInfo1(String name, {int age, double height}) {
        print('name=$name age=$age height=$height');
      }
      
      // 调用printInfo1函数
      printInfo1('xxx'); // name=xxx age=null height=null
      printInfo1('xxx', age: 18); // name=xxx age=18 height=null
      printInfo1('xxx', age: 18, height: 1.88); // name=xxx age=18 height=1.88
      // 顺序调换也可以
      printInfo1('xxx', height: 2.88, age: 28); // name=xxx age=28 height=2.88
      printInfo1('xxx', height: 1.88); // name=xxx age=null height=1.88
      
      • 位置可选参数定义方式:[param1, param2, ...]
      // 定义位置可选参数
      printInfo2(String name, [int age, double height]) {
        print('name=$name age=$age height=$height');
      }
      
      // 调用printInfo2函数
      printInfo2('xxx'); // name=xxx age=null height=null
      printInfo2('xxx', 18); // name=xxx age=18 height=null
      printInfo2('xxx', 18, 1.88); // name=xxx age=18 height=1.88
      
    • 可选参数可以设置默认值
    // 可选参数的默认值
    printInfo4(String name, {int age = 18, double height=1.88}) {
      print('name=$name age=$age height=$height');
    }
    
    • 函数可以作为变量定义或者作为其他函数的参数或者返回值
    main(List<String> args) {
      // 1.将函数赋值给一个变量
      var bar = foo;
      print(bar);
    
      // 2.将函数作为另一个函数的参数
      test(foo);
    
      // 3.将函数作为另一个函数的返回值
      var func = getFunc();
      func('kobe');
    }
    
    // 1.定义一个函数
    foo(String name) {
      print('传入的name:$name');
    }
    
    // 2.将函数作为另外一个函数的参数
    test(Function func) {
      func('kobe');
    }
    
    // 3.将函数作为另一个函数的返回值
    getFunc() {
      return foo;
    }
    
    • 匿名函数
    main(List<String> args) {
      // 1.定义数组
      var movies = ['少年', '你的答案', '缘字书', '不谓侠'];
    
      // 2.使用forEach遍历: 有名字的函数
      printElement(item) {
        print(item);
      }
      movies.forEach(printElement);
    
      // 3.使用forEach遍历: 匿名函数
      movies.forEach((item) {
        print(item);
      });
      movies.forEach((item) => print(item));
    }
    
    • 通过typedef定义个函数对象,增加可读性
    typedef Calculate = int Function(int num1, int num2);
    void test(Calculate calc) {
      var result = calc(20, 30);
      print(result);
    }
    

    运算符

    • 除法、整除、取模运算
    var num = 7;
    print(num / 3); // 除法操作, 结果2.3333..
    print(num ~/ 3); // 整除操作, 结果2;
    print(num % 3); // 取余/模操作, 结果1;
    
    • ??=:运算符
    // 1 当原来的变量有值时, 那么??=不执行
    var name = "kobe";
    name ??= "lilei";
    print(name);// kobe
    // 2 原来的变量为null, 那么将值赋值给这个变量
    var name1 = null;
    name1 ??= "lilei";
    print(name1);// lilei
    
    • 条件运算符:expr1 ?? expr2
    // 如果expr1是null,则返回expr2的结果;
    // 如果expr1不是null,直接使用expr1的结果
    var temp = 'yanhoo';
    var name = temp ?? 'kobe';
    print(name);// yanhoo
    var temp1 = null;
    var name1 = temp1 ?? 'kobe';
    print(name1);// kobe
    
    • 级联语法:..
    main(List<String> args) {
      // 分开调用
      final p1 = Person();
      p1.name = 'kobe';
      p1.run();
      p1.eat();
      p1.swim();
    
      // 通过级联语法
      final p2 = Person()
                  ..name = "kobe"
                  ..run()
                  ..eat()
                  ..swim();
    }
    
    // 自定义类
    class Person {
      String name;
    
      void run() {
        print("${name} is running");
      }
    
      void eat() {
        print("${name} is eating");
      }
    
      void swim() {
        print("${name} is swimming");
      }
    }
    

    流程控制

    • if和else
      • 注意:这里没有非0即真,非空即真
    • 循环操作
      • 基本的for循环
      • for in遍历List和Set类型
    • while和do-while和其他语言一致
    • break和continue用法也是一致
    • switch-case
      • 相对于OC,case语句后支持字符串

    泛型

    • 泛型的作用:我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样。但我们没有办法,只能分别写多个方法来处理不同的数据类型。这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种类型参数的办法呢?泛型的出现就是专门来解决这个问题的。
    • List和Map的泛型
    // ------------------- 创建List的方式 -------------------
    var names1 = ['why', 'kobe', 'james', 111];
    print(names1.runtimeType); // List<Object>
    
    // 限制类型
    var names2 = <String>['why', 'kobe', 'james', 111]; // 最后一个报错
    List<String> names3 = ['why', 'kobe', 'james', 111]; // 最后一个报错
    
    // ------------------- 创建Map的方式 -------------------
    var infos1 = {1: 'one', 'name': 'why', 'age': 18}; 
    print(infos1.runtimeType); // _InternalLinkedHashMap<Object, Object>
    
    // 对类型进行显示
    Map<String, String> infos2 = {'name': 'why', 'age': 18}; // 18不能放在value中
    var infos3 = <String, String>{'name': 'why', 'age': 18}; // 18不能放在value中
    
    • 定义泛型类
    
    main(List<String> args) {
      Location l2 = Location<int>(10, 20);
      print(l2.x.runtimeType); // int 
    
      Location l3 = Location<String>('aaa', 'bbb');
      print(l3.x.runtimeType); // String
    }
    }
    
    class Location<T> {
      T x;
      T y;
    
      Location(this.x, this.y);
    }
    
    • 限制泛型的范围
    main(List<String> args) {
      Location l2 = Location<int>(10, 20);
      print(l2.x.runtimeType);
        
      // 错误的写法, 类型必须继承自num
      Location l3 = Location<String>('aaa', 'bbb');
      print(l3.x.runtimeType);
    }
    
    // 限制泛型类型为继承自num的类型
    class Location<T extends num> {
      T x;
      T y;
    
      Location(this.x, this.y);
    }
    
    • 定义泛型方法
    main(List<String> args) {
      var names = ['Jordan', 'kobe'];
      var first = getFirst(names);
      print('$first ${first.runtimeType}'); // Jordan String
    }
    
    T getFirst<T>(List<T> ts) {
      return ts[0];
    }
    

    库的使用

    • Dart中任何一个dart文件都是一个库,即使你没有用关键字library声明
    • 通常在定义库时,我们可以使用library关键字给库起一个名字
    library math;
    
    • 库的导入
    // dart:前缀表示Dart的标准库,如dart:io、dart:html、dart:math
    import 'dart:io';
    
    //当然,你也可以用相对路径或绝对路径的dart文件来引用
    import 'lib/student/student.dart';
    
    //Pub包管理系统中有很多功能强大、实用的库,可以使用前缀 package:
    import 'package:flutter/material.dart';
    
    // 希望只导入库中某些内容,或者刻意隐藏库里面某些内容,可以使用show和hide关键字(这个功能个人感觉好鸡肋)
    import 'lib/student/student.dart' show Student, Person;
    import 'lib/student/student.dart' hide Person;
    
    • as关键字的作用:当各个库有命名冲突的时候,可以使用as关键字来定义一个命名空间用于区分
    import 'lib/student/student.dart' as Stu;
    
    // Stu.Student使用指定命名空间里的类
    Stu.Student s = new Stu.Student();
    
    • export关键字
    • 如果一个库文件很大,可以拆分成多个库,使用export关键字在某个库文件中集中导入
    mathUtils.dart
    dateUtils.dart
    
    可以新建一个utils.dart文件,并在文件中集中导入
    export 'mathUtils.dart';
    export 'dateUtils.dart'; 
    
    // 使用
    import "lib/utils.dart";
    
    • 补充:在Dart中如果有些方法不想被除当前库文件以外访问可以使用下划线
    // 这样定义的函数,当前库以外的就不能访问
    int _min(int num1, int num2) {
      return num1 > num2 ? num2: num1;
    }
    
    • 使用第三方的库文件
    • 首先创建pubspec.yaml,在文件中导入你要引用的三方库
    name: 自己去个有意义的名字
    description: 描述信息
    dependencies: 
      http: ^0.12.0+4
    
    • pub.dev无需科学上网)下载你要引用的三方库
    • 比如我搜索http,然后点击Installing按照说明进行引入 安装库
    • cd到.yaml文件所在的文件夹,在终端里执行pub get命令
    • 导入文件,三方库都是以package:开头
    import 'package:http/http.dart';
    

    相关文章

      网友评论

          本文标题:Flutter学习(三)Dart语法汇总

          本文链接:https://www.haomeiwen.com/subject/jkequhtx.html