Flutter و Dart: البنية والـ Widgets
فهم Flutter ومقابلته بما أتقنته في React Native. ⏱ نحو 40 دقيقة.
- تشرح ما
Flutterوكيف يختلف عنReact Nativeفي الرسم. - تقرأ شجرة
Widgetsوتقابلها بمكوّناتRN. - تميّز
StatelessWidgetعنStatefulWidgetوتربطهما بمفاهيمRN.
١Flutter بإيجاز
Flutter إطار Google لبناء تطبيقاتٍ متعدّدة المنصّات بلغة Dart. يختلف عن React Native جوهريًّا: بدل التحوّل إلى عناصر المنصّة، يرسم كل بكسلٍ بنفسه بمحرّك رسومٍ (Skia) — فيبدو موحّدًا عبر الأجهزة.
٢كل شيء Widget
في Flutter، الواجهة شجرة Widgets: كل شيءٍ widget — النصّ، الزرّ، الهامش، التوسيط. يقابل هذا «المكوّنات» في React Native:
| Flutter | React Native | الدور |
|---|---|---|
| Container | View | حاوية وتنسيق |
| Text | Text | نصّ |
Column / Row | View بـ flexDirection | ترتيب رأسيّ/أفقيّ |
| ElevatedButton | Pressable | زرّ |
| Image | Image | صورة |
هذه أول شاشةٍ في Flutter — لاحظ شجرة الـ Widgets المتداخلة:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Text('مرحبًا Flutter', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), Text('أول تطبيق بلغة Dart'), ], ), ), ), ); } }
Column يقابل View عمودية، وchildren يقابل الأبناء، وTextStyle يقابل كائن الأنماط. البنية نفسها بأسماءٍ مختلفة.
٣الحالة: Stateless مقابل Stateful
كما في React لدينا مكوّناتٌ بلا حالة وأخرى بحالة. في Flutter: StatelessWidget (ثابت) وStatefulWidget (متغيّر). عدّادٌ بحالة:
class Counter extends StatefulWidget { const Counter({super.key}); @override State<Counter> createState() => _CounterState(); } class _CounterState extends State<Counter> { int count = 0; // الحالة @override Widget build(BuildContext context) { return Column( children: [ Text('العدّاد: $count'), ElevatedButton( onPressed: () => setState(() => count++), // يشبه setState في React child: const Text('زيادة'), ), ], ); } }
| المفهوم | React Native | Flutter |
|---|---|---|
| مكوّن بلا حالة | دالّة تعيد JSX | StatelessWidget |
| مكوّن بحالة | useState | StatefulWidget + setState |
| تحديث الواجهة | تغيّر الحالة | setState(() => …) |
لاحظ setState في الاثنين! المبدأ واحد: غيّر الحالة، فتُعاد بناء الواجهة. ما تعلّمته في React Native ينقلك نصف الطريق في Flutter.
توقّع وتحقّق
لغة Flutter:
كيف يرسم Flutter الواجهة؟
يقابل View في Flutter:
المكوّن ذو الحالة في Flutter:
الخلاصة
FlutterإطارGoogleبلغةDart، يرسم كل بكسلٍ بمحرّكه.- كل شيءٍ
Widget؛Column↔View،Text↔Text،ElevatedButton↔Pressable. StatefulWidget + setStateيقابلuseState— المبدأ واحد.
تحدٍّ برمجي: ترجمة من Flutter إلى React Native
متوسطأمامك عدّاد Flutter أعلاه. اكتب مكافئه بـ React Native.
- استخدم
useStateلعدّادٍ يبدأ من 0. <Text testID="count">يعرض قيمة العدّاد.Pressableيزيد العدّاد عند اللمس.
👀 اعرض الناتج المطلوب (وجرّبه)
- الكود يعمل بلا أخطاء في Console
- العدّاد يبدأ من 0
- بعد اللمس يصبح 1
- استُخدم useState
💡 تلميح 1
💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
import { useState } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native'; export default function App() { const [count, setCount] = useState(0); return ( <View style={{ padding: 20, alignItems: 'center', gap: 10 }}> <Text testID="count" style={styles.n}>العدّاد: {count}</Text> <Pressable style={styles.btn} onPress={() => setCount(count + 1)}> <Text style={styles.bt}>زيادة</Text> </Pressable> </View> );} const styles = StyleSheet.create({ n: { fontSize: 22, fontWeight: 'bold', color: '#E8820C' }, btn: { backgroundColor: '#E8820C', padding: 12, borderRadius: 10 }, bt: { color: 'white' },});