秀髮去無蹤之你不得不知道的Dart

引言

最近flutter發展的如火如荼,而Dart做爲flutter的開發語言,瞭解一下伐?html

語言特徵

dart 中一切皆對象 dart這個特徵和java很像,全部變量、方法都是對象,那怕僅僅是個數字或字符串前端

入口函數

在dart項目中,必須聲明一個入口函數main,這也很java,程序從main函數開始運行(習慣使用js的須要注意這一點)。java

void main(){
  print('hello dart!')
}
複製代碼

變量聲明

  • 通常聲明變量必須明確類型,類型明確後不能改變,未賦值默認值都是null
    int i = 2;
    i = '3' ; // error:i爲int類型,不能賦值字符串類型
    複製代碼
  • var 能夠聲明任意類型的變量,賦值後類型不能再改變
    var i;
    i = 2; 
    i = 3;
    i = '4'; // error: var 變量賦值後,類型不能再改變
    複製代碼
  • dynamic 能夠聲明動態類型的變量,每次賦值類型不受限制
    dynamic d = 1;
    d = '123'; // 變量類型肯定後還能夠再賦值其餘類型
    複製代碼
  • final 變量只能賦值一次,聲明時必須初始化
    final a = 1;
    a = 2; // error: final變量只能賦值一次,再次賦值報錯
    
    final b = [2];
    b[0] = 1;
    b.add(2); // final 雖然不能再次賦值,可是能夠改變他成員變量的值
    複製代碼
  • const 變量是編譯時常量,是一種特殊的final變量
    const a = 1;
    a = 2; // error: const變量只能在初始化時賦值
    
    const b = [2];
    b.add(2); // error: const 變量中的成員變量也不可再次改變
    複製代碼

方法

  • 通常定義方法須明確入參個數、類型及出參的類型
    // 方法定義,明確入參和出參,編譯時能夠作類型校驗,提早發現一些錯誤
    int add(int m, int n) {
      return m + n;
    }
    void main() {
      int a = add(50, 30);
      String b = add('50', 30); // error: 入參類型和出參類型不正確,編譯不經過
    }
    複製代碼
  • 若是不明肯定義方法入參和出參參數類型,編譯時沒法進行類型檢查
    // 出參和入參的類型能夠忽略,若是忽略,編譯時沒法進行類型檢查
    add( m, n) {
      return m + n;
    }
    void main() {
      int a = add(50, 30);
      String b = add('50', 30); // 能夠經過編譯,但在運行時會報異常
    }
    複製代碼
  • 方法入參也可使用基於命名或位置的可選參數
    // 可選位置參數
    // 可選參數後面不能再有參數
    int add(int m, [int n]) {
      int sum = m;
      if (n != null) {
        sum += n;
      }
      return sum;
    }
    
    void main() {
      print(add(1));
      print(add(1, 2));
    }
    複製代碼
    // 可選命名參數
    int add({int m, int n}) {
      int sum = 0;
      if (m != null) {
        sum += m;
      }
      if (n != null) {
        sum += n;
      }
      return sum;
    }
    
    void main() {
      print(add());
      print(add(m: 1));
      print(add(n: 2));
      print(add(m: 1, n: 2));
    }
    複製代碼
  • 定義方法入參時能夠定義可選參數的默認值,默認值必須是編譯時常量
    // 默認參數值
    // 默認值只能給可選參數設置
    // 位置可選參數匹配順序是從左到右的,即使有默認參數值
    int add(int m, [int n = 0, int i]) {
      var sum = m + n;
      if (i != null) {
        sum += i;
      }
      return sum;
    }
    
    void main() {
      print(add(1));
      print(add(1, 2));
    }
    複製代碼
  • 箭頭函數只能跟一個表達式,不能使用語句和代碼塊(前端開發人員要特別注意,和js的箭頭函數不一樣)
    // => 函數
    void main() {
      var add = (int m, int n) => m + n;
      var sub = (int m, int n) => return m - m; // error: ruturn 是代碼語句,箭頭函數不能使用代碼語句
      add(1 , 2);
    }
    複製代碼
  • 當方法做爲參數傳遞給高階方法時,可使用匿名方法
    // 匿名函數
    void main() {
      var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums'];
      list.forEach((i) {
        print(list.indexOf(i).toString() + ': ' + i);
      });
    }
    複製代碼
    也可使用箭頭函數爲高階方法傳參
    // 匿名函數
    void main() {
      var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums'];
      // 轉換爲箭頭函數時,要去掉語句後面的分號,
      // 有分號就是語句,沒有分號就變成了表達式,符合箭頭函數要求
      list.forEach((i) => {print(list.indexOf(i).toString() + ': ' + i)});
      // 或
      list.forEach((i) => print(list.indexOf(i).toString() + ': ' + i));
    }
    複製代碼
  • Dart是靜態做用域語言,編譯時變量的做用域就已經肯定(這點也和js不一樣,前端開發人員需注意)
    // 靜態做用域
    int a = 5;
    class Test {
      int a = 6;
      int getA() {
        return a;
      }
    }
    
    void main() {
      var obj = new Test();
      print(obj.getA()); // 6
      var fun = obj.getA;
      print(fun()); // 6
    }
    複製代碼

操做符

  • 除法( / ), 整除(~/)
    void main() {
      print('5/2 = ${5 / 2}'); // 5/2 = 2.5
      print('5~/2 = ${5 ~/ 2}'); // 5~/2 = 2
    }
    複製代碼
  • 類型轉換(as), 類型判斷(is、is!), as 只能從父類型轉子類型, is 判斷變量是某種類型, is!和is相反,判斷變量不是某種類型
    void main() {
      num a = 123;
      // print(a.isOdd); // error: isOdd 不是num的成員變量
      print((a as int).isOdd);// isOdd 是int的成員方法,全部a必須轉換成int類型後再調用
      print('a is not String ? ${a is! String}'); // a is not String ? true
      print('a is int ? ${a is int}'); // a is int ? true
    }
    複製代碼
  • ??= 爲值爲null的變量賦值
    void main() {
      var a;
      a ??= 1; // 賦值前a = null,賦值後 a=1
      a ??= 2; // 賦值前 a = 1, 賦值後 a=1
      print(a); // 1
    }
    
    複製代碼
  • expr1 ?? expr2, 等價於 expr1 != null ? expr1 : expr2
    void main() {
      var a;
      var b = 1;
      print(a ?? b); // 1
      a = 0;
      print(a ?? b); // 0
    }
    複製代碼
  • 級聯操做(..)能夠在同一個對象上連續調用多個函數及訪問成員變量
    // '..'不一樣於'.',不要求函數有返回值,'..'至關於普通函數執行後返回‘this’
    class Car {
      void move(String direction, double distance) {
        print('小汽車向${direction}行駛了${distance} 公里');
      }
    
      Car run(String direction, double distance) {
        print('小汽車向${direction}行駛了${distance} 公里');
        return this;
      }
    }
    
    void main() {
      Car car = new Car();
      car..move('東', 3)..move('南', 4)..move('西', 4)..move('北', 4);
      car..move('東', 3)..run('西', 3)..run('北', 4).run('西', 4).run('北', 4);
    }
    複製代碼
  • a?.b 若是a爲null,則返回null,不然返回a.b
    void main() {
      int a;
      // print(a.isOdd); // error: a未賦值,不能訪問成員變量和成員函數
      print(a?.isOdd);
      // 至關於
      if (a == null) {
        print(null);
      } else {
        print(a.isOdd);
      }
    }
    複製代碼

  • 每一個對象都是一個類的實例,全部的類都集成於Object
    void main() {
      int a = 1;
      print(a is Object); // true
    }
    複製代碼
  • 每一個類都只能有一個父類,可是能夠同時實現多個接口,一個父類能夠同時被多個子類繼承
    class Tiger extends Animal implements Fly, Swim {
      // todo
    }
    class Dog extends Animal {
      // todo
    }
    複製代碼
  • 每一個實例變量都會自動生成一個getter方法,Non-final實例變量還會自動生成一個setter方法
    class Test {
      int a;
      // 至關於
      // int _a;
      // int get a => _a;
      // set a(int val) => this._a = val;
    }
    複製代碼
  • 定義一個和類名字同樣的方法就定義了一個構造函數,還能夠帶有其餘可選的標識符,若是沒有定義,會生成一個不帶參數的默認構造函數,構造函數不會被繼承
    class Parent {
      String name;
      Parent(this.name);
    }
    
    class Child extends Parent {
      Child(String name) : super(name);
      Child.create(String name) : super(name);
    }
    void main(){
      var zhangsan = Child('張三');
      var lisi = Child.create('李四');
    }
    複製代碼
  • 可使用abstract來定義抽象類,抽象類不能被實例化。抽象類一般含有抽象方法,抽象方法只有方法簽名,沒有實現。
    abstract class Animal {
      // 抽象方法
      void moving();
    }
    複製代碼
  • 用extends來實現繼承,用implements來實現接口,使用@override來從新父類方法
    class Animal {
      final String name;
      Animal(this.name);
    
      void moving() {
        print('${this.name}正在移動');
      }
    }
    
    abstract class Fly {
      // 抽象方法
      void fly();
    }
    
    class Tiger extends Animal implements Fly {
      Tiger() : super('老虎');
      @override
      void fly() {
        print('如虎添翼');
      }
    }
    複製代碼
  • 用static定義靜態變量和靜態方法
    class Calculator {
      static int Add(int m, int n) {
        return m + n;
      }
    }
    void main(){
      print(Calculator(1, 2));
    }
    複製代碼

庫的使用

  • 經過import來引入庫
  • 引用內部庫 import 'dart:schema',如:import 'dart:io';
  • 引用外部庫 import 'package:schema', 如:import 'package:utils/utils.dart';
  • 能夠經過 as 來指定庫前綴,如 import 'package:utils/utils.dart' as utils;
  • 能夠經過 showhide 來部分導入庫
  • 能夠經過 deferred as 延遲加載一個庫

dart 核心庫

  • dart:core 提供了基礎類型、集合和其餘少許可是很是核心的功能,dart應用會自動導入這個庫。
  • dart:convert 提供了一些用來轉換 JSON 和 UTF-8 的轉換器,還能夠自定義 新的轉換器。
  • dart:async 異步編程一般使用回調函數,可是 Dart 提供了另外的 選擇: Future 和 Stream 對象。
  • dart:html 爲基於web的應用提供了操做Dom元素和使用HTML5 API的功能。
  • dart:math 提供了經常使用的數學運算功能。
  • dart:io 提供了一下文件讀寫、進程訪問、sockets等相關的功能,只有命令行應用可使用。

PUB

pub相似於node的npm,用於管理dart應用的包,詳情參見pub.dev/node

總結

瞭解了上面這些基礎語法,基本上就能夠看懂一些dart示例和源碼了,想有所成,瞭解這些仍是遠遠不夠的,可是這些能夠做爲一個開始,做爲學習dart的起點。web

參考

關於咱們

快狗打車前端團隊專一前端技術分享,按期推送高質量文章,歡迎關注點贊。
文章同步發佈在公衆號喲,想要第一時間獲得最新的資訊,just scan it !npm

公衆號二維碼
相關文章
相關標籤/搜索