[Flutter翻譯]通往Flutter Web的旅程第二部分:用Fluro進行路由選擇

Sunbreak發表於2021-06-01

原文地址:medium.com/flutter-cla…

原文作者:medium.com/@hiashutosh

釋出時間:2021年4月29日 - 5分鐘閱讀

image.png

照片:Max Avans on Pexels

如果你是直接來到這個頁面,請確保你在開始這個頁面之前,先瀏覽一下《走向Flutter Web Part:1》

現在你可能想知道?為什麼我們需要再次處理路由?

試著在網路上重新整理專案中的任何一個螢幕,你會發現整個專案重新構建,你的應用程式從第一個螢幕開始,或者你也可能觀察到一個紅色的螢幕,就像我在aqi_monitor專案中重新整理LocationScreen時那樣。

image.png

讓我們分析一下為什麼會發生這種情況?

在引擎蓋下發生的事情是,資料只持續到我們重新整理Flutter專案的時候。所有那些我們通過建構函式傳遞給特定螢幕的值都變成了空值,因為沒有以前的上下文。類似的問題開始出現在狀態管理包中,比如provider,因為我們的Provider物件被返回到他們的基本狀態。

如果你使用Navigator 1.0設定了路由,你應該遷移到支援網路的Navigator 2.0,或者使用像Fluro這樣的包。

Fluro如何解決這個問題?

Fluro提供了一些開箱即用的功能,這些功能是。

  • 查詢引數的解析
  • 每個螢幕的功能處理程式
  • 在手機和網頁上的工作完全相同
  • 很容易根據平臺型別在螢幕之間新增過渡。

我們可以按照以下步驟在我們的專案中設定Fluro:----。

1. 在pubspec.yaml檔案中新增fluro的依賴項

dependencies:
  fluro: 2.0.3
複製程式碼

新增依賴後,執行flutter pub get

2. 在lib/routes/內建立FluroRoutes類,作為fluro_routes.dart

/// setting up singleton class for FluroRoutes

class FluroRoutes with FluroRouteHandlers {
  
/// initializing FluroRoutes  
static final FluroRoutes fluroRoutesInstance = FluroRoutes._();

  factory FluroRoutes() {
    return fluroRoutesInstance;
  }

  FluroRoutes._();

  void routes(FluroRouter fluroRouter) {
    TransitionType transitionType;

    /// setting transition on web
    if (kIsWeb) {
      transitionType = TransitionType.fadeIn;
    }

    /// setting transition on android
    else if (Platform.isAndroid) {
      transitionType = TransitionType.material;
    }

    /// setting transition on iOS
    else {
      transitionType = TransitionType.cupertino;
    }

    /// linking handlers and routes of screen
    fluroRouter.define(
      MyHomePage.routeName,
      handler: homeScreenHandler,
      transitionType: transitionType,
    );

    fluroRouter.define(
      LocationScreen.routeName,
      handler: locationScreenHandler,
      transitionType: transitionType,
    );
  }
}
複製程式碼

在這裡,我們為FluroRoutes建立了一個單例類,我們宣告瞭一個過渡型別,它將取決於作業系統,並宣告瞭專案的所有螢幕路由,並與它們的具體處理程式相聯絡。

3. 在lib/routes/內建立FluroRouteHandlers作為fluro_route_handlers.dart

mixin FluroRouteHandlers {
  /// Handler for MyHomePage
  var homeScreenHandler = Handler(
    handlerFunc: (
      BuildContext context,
      Map<String, List<String>> parameters,
    ) {
      return MyHomePage();
    },
  );
  /// Handler for LocationScreen
  var locationScreenHandler = Handler(
    handlerFunc: (
      BuildContext context,
      Map<String, List<String>> parameters,
    ) {
      return LocationScreen();
    },
  );
}
複製程式碼

在這裡,處理程式的作用是提供所需的引數(我們將在這篇文章的後面看到)並啟動螢幕。

4. 在main.dart中設定FluroRoutes

在MaterialApp中設定你的FluroRoutes。

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
final FluroRouter fluroRouter = FluroRouter();

@override
void initState() {
  super.initState();

  /// setting up FluroRoutes with fluroRouter
  FluroRoutes().routes(fluroRouter);
}
@override
Widget build(BuildContext context) {  
 return MaterialApp(
   title: "AQI Monitor",
   home: MyHomePage(title: 'AQI Monitor'),

   /// pass you initial screen's route in initialRoute
   initialRoute: MyHomePage.routeName,

   /// use fluro's generator
   onGenerateRoute: fluroRouter.generator,
   onUnknownRoute: (unknownRoutes) {
     return MaterialPageRoute(
       builder: (context) => MyHomePage(),
     );
   },
 );
   }
}
複製程式碼

在網路上,由於我們可以通過改變URL進入另一個螢幕,而這將把你帶到一個不存在於你的專案中的未知螢幕,所以我們可以重定向到專案中的一個初始螢幕(如閃屏、主螢幕),或者像樣在你的專案中製作一個自定義的404螢幕,我們可以在onUnknownRoute中利用它。

5. 更新導航過程

現在我們已經正確地設定了Fluro,我們現在將更新每個螢幕的導航過程。

i) 使用Navigator進行簡單的導航。

Navigator.pushNamed(context, LocationScreen.routeName)。

Navigator.pushNamed(context, LocationScreen.routeName);
複製程式碼

不要使用MaterialPageRoute在螢幕間導航,只使用Navigator。

ii) 使用QueryParams來傳送資料

像這樣修改你的模型和引數。

class CityModel {
  String city;

  CityModel({
    this.city,
  });

  CityModel.fromJson(Map<String, dynamic> json) {
    city = json['city'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['city'] = city;
    return data;
  }

  String toQueryParam() {
    return Uri(queryParameters: toJson()).query;
  }

  CityModel.fromQueryParam(Map<String, dynamic> jsonMap) {
    city = jsonMap['city']?.first;
  }
}
複製程式碼

toQueryParam是我們上面的輔助函式,它將我們模型的JSON轉換為查詢格式。

fromQueryParam是另一個輔助函式,將我們的查詢引數轉換回模型。

現在用"?"(強制)符號連線螢幕路線名稱和查詢引數。

Navigator.pushNamed(
  context,
  LocationScreen.routeName + '?${cityModel.toQueryParam()}',
);
複製程式碼

在最後一步,我們現在將通過使用我們的輔助函式來修改我們的處理程式。我們在Navigator中傳遞的查詢引數,我們將在處理程式中使用fromQueryParam幫助函式將它們轉換為我們的模型,並在我們的螢幕中傳遞該模型或其值。

var locationScreenHandler = Handler(
  handlerFunc: (
    BuildContext context,
    Map<String, dynamic> parameters,
  ) {
    CityModel cityModel;
    if (parameters != null && parameters.isNotEmpty) {
      cityModel = CityModel.fromQueryParam(parameters);
    }
    return LocationScreen(
      city: cityModel != null ? cityModel.city : null,
    );
  },
);
複製程式碼

現在,在網路上執行你的專案,也嘗試用與之前相同的方式重新整理螢幕。

你會觀察到,我們的螢幕在重新整理後仍然在同一個螢幕事件上,而且之前出現的紅屏也應該消失了,因為查詢引數仍然在URL中,Fluro通過處理程式將這些查詢引數傳遞給我們的螢幕,這個設定在Android和iOS上也都能順利執行。

所以這就是設定這個新的整個路由機制的好處。?

image.png

image.png

重要提示:請確保在處理程式中處理所有的引數和模型,我們從一個螢幕傳送到另一個螢幕,你只需要將它們轉換為查詢引數,在導航時與路由一起新增,然後從查詢引數解碼回到模型中。

在下一篇文章中,我們將討論如何通過保持相同的程式碼庫使UI在網路和移動端上都能響應。


如果你覺得這篇文章有用,請點選拍手圖示?並與你的朋友分享,因為這將激勵我寫更多的文章。

如有任何關於Flutter的疑問,請隨時在社交媒體平臺上與我聯絡。

linktr.ee/hiahutoshsi…


通過www.DeepL.com/Translator(免費版)翻譯

相關文章