Flutter 高效自學筆記(二)

Flutter 高效自學筆記(一)網絡

這是上篇文章文末提到的「第三個教程」的快速自學筆記。app

Widget 部件

讀音 /'wɪdʒɪt/ 危機特,文檔說借鑑了 React。我認爲 Widget 至關於 React 裏的組件 Component。less

下文將 Widget 所有稱爲「部件」。ide

部件的特色函數

  1. 基於你傳給它配置和 state 生成視圖
  2. 當一個部件的 state 變化了,部件就會更新視圖
  3. Flutter 會對比新舊視圖的區別,對實際視圖作最小化的變更

runApp

這是 Flutter 應用必須調用的 API,接受一個部件。我的認爲這很像是 React 的 ReactDOM.render 操做。佈局

import 'package:flutter/material.dart';

void main() {
  runApp(
    Center(
      child: Text(
        'Hello, world!',
        textDirection: TextDirection.ltr,
      ),
    ),
  );
}
複製代碼

以上代碼的做用:post

  1. Center 是個類,Center() 就是實例化出一個實例
    1. 我很是欣賞刪掉 new 的作法,不再會有人問 Center() 和 new Center() 的區別了,fuck JS。
  2. Center(...) 返回一個部件,做爲根部件
  3. Center(...) 部件的子部件是 Text(...),若是隻有一個子組件就用 child,若是有多個子組件就用 children
  4. Flutter 會強行讓根部件佔滿屏幕(好評),因此最終效果就是屏幕中央有個 Hello, world! 字符串
  5. 代碼中須要用 textDirection 指明文字方向,你用 MaterialApp 就能夠省掉這一步,後面會講
  6. 全部的部件類要麼是 StatelessWidget 的子類,要麼是 StatefulWidget 的子類
  7. 一個部件的主要功能是提供 build 方法(我的認爲相似於 React 的 render),build 方法能夠調用更多其餘部件
  8. Flutter 會遍歷這些子部件,而後計算出當前部件的結構

基礎部件

經常使用的部件有:flex

  • Text:顧名思義
  • Row 和 Column:佈局用的,相似於 CSS 的 flex 佈局
  • Stack:佈局用的,相似於 CSS 的絕對佈局
  • Container:通用佈局,相似於 div

MaterialApp

若是你想用一些 Material 風格的部件,只須要作這幾件事就能夠:動畫

  1. 在 pubspec.yml 裏添加以下代碼ui

    flutter:
         uses-material-design: true
    複製代碼
  2. runApp 的時候使用 MaterialApp,並使用 Material 部件

    runApp(MaterialApp(
         title: 'My app', // used by the OS task switcher
         home: Material(),
     ));
    複製代碼
  3. import 'package:flutter/material.dart';

經常使用的 Material 部件

  1. Navigator:相似於 ReactRouter

  2. AppBar:頂部的 bar

    AppBar(
         leading: IconButton(
             icon: Icon(Icons.menu),
             tooltip: 'Navigation menu',
             onPressed: null,
         ),
         title: Text('Example title'),
         actions: <Widget>[
             IconButton(
             icon: Icon(Icons.search),
             tooltip: 'Search',
             onPressed: null,
             ),
         ],
     )
    複製代碼
  3. Scaffold: 最經常使用的佈局部件

    Scaffold(
       appBar: AppBar(...),
       body: Center(...),
       floatingActionButton: ...
     );
    複製代碼

這些傳參方式很像 Vue 的命名插槽。

用 GestureDetector 處理用戶交互

這是一個自定義 button 部件:

class MyButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(               // <-- 注意看這裏
      onTap: () {
        print('MyButton was tapped!');
      },
      child: Container(
        height: 36.0,
        padding: ...,
        margin: ...,
        decoration: ...,
        child: Center(
          child: Text('Engage'),
        ),
      ),
    );
  }
}
複製代碼
  1. GestureDetector 部件並無任何表現層,只處理用戶交互。當用戶點擊 Container 部件時,會觸發 GestureDetector 部件的 onTap 回調。
  2. GestureDetector 支持的交互至關多,如輕觸、拖曳和縮放。
  3. 不少其餘部件都藉助 GestureDetector 來接收回調,如 IconButton, RaisedButton 和 FloatingActionButton 都接收 onPressed 回調。

改變 state

無狀態部件從父級接收數據,並把數據存在本身的 final 成員變量裏(相似於 JS 的 const)。

有狀態的部件則知道如何建立 state 對象,並維持 state 對象。

如何使用呢?

首先聲明一個 StatefulWidget

class Counter extends StatefulWidget {
  @override
  _CounterState createState() => _CounterState();
}
複製代碼

這個部件須要重寫 createState 方法,而這個方法的返回值的類型,必須繼承自 State 類。

_CounterState 是如何繼承 State 的呢

class _CounterState extends State<Counter> {
  int _counter = 0;

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        RaisedButton(
          onPressed: _increment,
          child: Text('Increment'),
        ),
        Text('Count: $_counter'),
      ],
    );
  }
}
複製代碼
  1. 須要重寫 build 方法提供視圖,並且可使用 '$_counter' 混入語法
  2. 在按鈕被點擊的時候調用 _increment,這個 _increment 會調用 State 提供的 setState 函數,給 setState 函數傳入一個函數,這個傳入的函數能夠對數據進行修改。
  3. 很是像 React 的 Class 組件。區別在於
    1. Flutter 的部件和 state 是分開的類,而 React 只是把 state 用一個 hash 表示。
    2. Flutter 的 State 裏面提供 build 方法,而 React 的 state 只是一個 hash
    3. Flutter 將 StatelessWidget 和 StatefulWidget 分開,能更好地組織代碼

生命週期

StatefulWidget 有 createState 方法,State 有 initState 方法。

Flutter 調用 createState 方法後,獲得一個 State 對象,而後調用這個 State 對象的 initState 方法。

你的自定義 State 類能夠重寫 initState 方法,這個方法只會調用一次。好比你能夠重寫 initState 來配置動畫或者訂閱事件。

當一個 State 對象快死的時候,Flutter 會調用 State 對象的 dispose 方法。你也能夠重寫 dispose 方法,好比在裏面取消 timer 或者取消訂閱。

keys

Flutter 默認是經過部件的 runtimeType 和出現順序來肯定一個部件的身份的,這樣才能在對比新舊部件樹的過程當中肯定哪一個是哪一個。若是你給部件賦予了 key,那麼就不用根據「出現順序」來惟一肯定組件了,由於這種方式不太靠譜。

我的認爲跟 React 的 key 有相同的做用。

key 分爲兄弟間的 key 和全局 key。目前還不知道應用場景的區別。大部分時候應該只須要用兄弟間的 key 用來區分兄弟就好了。


下一篇文章打算看看 Flutter 如何發起網絡請求。

未完待續……

相關文章
相關標籤/搜索