مقدمة إلى GoRouter
مقدمة إلى GoRouter
مع نمو تطبيقات Flutter وازدياد تعقيدها، قد تصبح واجهة برمجة تطبيقات Navigator المدمجة صعبة الإدارة. GoRouter هو حزمة توجيه تصريحية رسمية من فريق Flutter تُدخل التنقل المستند إلى عناوين URL، والربط العميق، وهيكل شجرة مسارات نظيف. بدلاً من دفع المسارات وإزالتها بشكل أمري، تعلن تسلسل المسار بالكامل مسبقاً وتتنقل باستخدام مسارات تشبه عناوين URL.
go_router على pub.dev.إضافة go_router إلى مشروعك
ابدأ بإضافة التبعية إلى ملف pubspec.yaml الخاص بك:
pubspec.yaml
dependencies:
flutter:
sdk: flutter
go_router: ^14.0.0
بعد حفظ الملف، شغّل flutter pub get في طرفيتك لجلب الحزمة. ثم استوردها حيثما تقوم بتهيئة التوجيه:
استيراد GoRouter
import 'package:go_router/go_router.dart';
الإعلان عن شجرة مسارات باستخدام GoRoute
يتطلب GoRouter منك الإعلان عن شجرة مسارات — قائمة من إدخالات GoRoute تربط مسارات URL بالودجات. كل GoRoute يحدد path وbuilder (أو pageBuilder) يُعيد الودجت للعرض. ثم تمرر نسخة GoRouter إلى منشئ MaterialApp.router.
تعريف GoRouter بمسارات متعددة
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
final GoRouter _router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) {
return const HomeScreen();
},
),
GoRoute(
path: '/profile',
builder: (BuildContext context, GoRouterState state) {
return const ProfileScreen();
},
),
GoRoute(
path: '/product/:id',
builder: (BuildContext context, GoRouterState state) {
final String productId = state.pathParameters['id']!;
return ProductScreen(productId: productId);
},
),
],
);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'GoRouter Demo',
routerConfig: _router,
);
}
}
GoRouter الخاصة بك كمتغير على المستوى الأعلى أو محدد النطاق بالموفر، وليس داخل طريقة build الخاصة بالودجت. إعادة إنشاء الموجه عند كل إعادة بناء تتسبب في إعادة تعيين حالة التنقل بشكل غير متوقع.التنقل باستخدام context.go و context.push
يضيف GoRouter أساليب امتداد مباشرة على BuildContext حتى تتمكن من التنقل في أي مكان في شجرة الودجات دون الحاجة إلى مرجع لكائن الموجه. الأسلوبان الأهم هما:
context.go(path)— يستبدل مكدس التنقل بالكامل بالمسار الجديد. لا يستطيع المستخدم الضغط على زر الرجوع للعودة. استخدمه للتنقل على المستوى الأعلى كتبديل التبويبات أو الذهاب إلى الشاشة الرئيسية بعد تسجيل الدخول.context.push(path)— يدفع المسار الجديد فوق المكدس الحالي مع الحفاظ على سلوك زر الرجوع. استخدمه للتعمق في التفاصيل: الانتقال من قائمة إلى شاشة تفاصيل.
استخدام context.go و context.push
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('الرئيسية')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
// يستبدل المكدس — لا زر رجوع للرئيسية
context.go('/profile');
},
child: const Text('الذهاب إلى الملف الشخصي'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
// يدفع فوق المكدس — زر الرجوع يعيد هنا
context.push('/product/42');
},
child: const Text('عرض المنتج 42'),
),
],
),
),
);
}
}
معاملات المسار ومعاملات الاستعلام
يدعم GoRouter كلاً من معاملات المسار (شرائح مسبوقة بنقطتين مثل :id) ومعاملات الاستعلام (أزواج مفتاح-قيمة بعد ?). يمكن الوصول إليها من خلال كائن GoRouterState الممرر لكل منشئ:
state.pathParameters['id']— يستخرج قيمة شريحة المسارstate.uri.queryParameters['filter']— يستخرج قيمة سلسلة الاستعلام
لتمرير معامل استعلام عند التنقل، ما عليك سوى إلحاقه بسلسلة المسار:
مثال على معاملات المسار والاستعلام
// التنقل مع معامل استعلام
context.go('/profile?tab=settings');
// في منشئ المسار:
GoRoute(
path: '/profile',
builder: (BuildContext context, GoRouterState state) {
final String tab = state.uri.queryParameters['tab'] ?? 'overview';
return ProfileScreen(initialTab: tab);
},
),
استبدال Navigator.push بـ GoRouter
إذا كنت تُهاجر تطبيقاً موجوداً، استبدل كل استدعاء Navigator.push(context, MaterialPageRoute(builder: ...)) باستدعاء context.push('/path')، وكل استدعاء Navigator.pushReplacement(...) بـ context.go('/path'). هذا يجعل نية التنقل واضحة ويتيح الربط العميق تلقائياً.
Navigator.push وcontext.go/context.push في التطبيق نفسه إلا إذا فهمت تماماً كيف يتفاعل GoRouter مع Navigator الأساسي. يمكن أن يُنتج الخلط بينهما سلوكاً غير متوقع لمكدس الرجوع، خاصة على الويب.الملخص
يُحضر GoRouter التوجيه التصريحي المستند إلى عناوين URL إلى Flutter. تُضيف حزمة go_router، وتُعرّف شجرة مسارات بإدخالات GoRoute في نسخة GoRouter، وتربطها بـ MaterialApp.router، وتتنقل باستخدام context.go() (استبدال المكدس) أو context.push() (إضافة إلى المكدس). يتم الإعلان عن معاملات المسار والاستعلام في سلسلة مسار المسار والوصول إليها عبر GoRouterState. هذا الأساس يجعل الربط العميق والتنقل المتداخل ومزامنة URL أمراً مباشراً في تطبيقات Flutter سواء للجوال أو الويب.
context.go() عندما تريد استبدال تاريخ التنقل (مثلاً بعد تسجيل الدخول) وcontext.push() عندما تريد أن يتمكن المستخدم من الضغط على رجوع (مثلاً عند عرض شاشة التفاصيل). شجرة المسارات المعلنة في GoRouter هي المصدر الوحيد للحقيقة لجميع عمليات التنقل في تطبيقك.